このページでは、新しいバージョンのブラウザが公開されても壊れることのない Web サイトを記述する方法を説明します。
これはイントラネットや公衆向けでない Web サイトで特に重要です。私たちがあなたのコードを見ることができないので、それが壊れていることを確認できないのです。これらのすべてに従うことができない場合もありますが、可能な限り多くの事項に従うことで、Web サイトを将来にわたって有用な状態にすることの助けになります。
JavaScript
onfoo
属性でグローバル変数へアクセスする際に "window
." 接頭辞を付加する
HTML の要素でイベントハンドラのコンテンツ属性 (onclick
、 onmouseover
など) が使用されているとき、それら属性でのすべての名前探索は始めに要素自身、次にフォームコントロール要素の場合はそのフォーム、そして document、さらに (あなたがグローバル変数を定義した) window の順に行われます。例えば、以下のマークアップがある場合は:
<div onclick="alert(ownerDocument)">Click me</div>
文字列をクリックすると div
の ownerDocument
をアラートで表示します。これは、var ownerDocument
がグローバルスコープで宣言されている場合でも動作します。
これが意味することは、イベントハンドラのコンテンツ属性でグローバル変数にアクセスするときやグローバルに宣言された任意の関数を呼び出すとき、あなたの関数や変数と同じ名前の新たな DOM プロパティが仕様書で要素やドキュメントに追加され、またそれをブラウザが実装した場合に、常に名前が衝突した時点で探索が終わってしまいます。これが起きると、突如関数が呼び出されなくなります。この現象は HTML5 の進展に伴い、さまざまなサイトで何度も発生しています。
これを防ぐには、以下のように "window." を用いてグローバル変数にアクセスするのが最適です:
<script> function localName() { alert('Function localName has been called'); } </script> <div onclick="window.localName()">Clicking me should show an alert<div>
自身で管理しないスクリプトを連結しない
ファイルレベルで使用される ECMAScript の "use strict;"
ディレクティブは、ファイル全体に適用されます。このため、非 Strict モードの動作に依存するスクリプトを Strict モードのスクリプトに付加すると、スクリプトが動作しなくなります。
使用する JavaScript ライブラリの作者に、上記のガイドラインに従っているかを確認する
好みのライブラリの開発者に、上記のガイドラインに従うことを提案しましょう。彼らが従わない場合、ライブラリが将来も問題を起こさないとは信頼できません。残念ながら、ライブラリはこれらのガイドラインに逆らっています。
検出
特定の機能の検出
ある機能を用いようとするとき、可能であればその機能を見つけるためにオブジェクト検出を行ってください。簡単な例として、body.style
に "filter"
があるかのテストが真になるブラウザは必ず Microsoft Internet Explorer であり、それゆえ例えばイベントハンドラで window.event
オブジェクトが利用できるとは考えないでください。また、ある一定の DOM 機能をサポートしているブラウザは他の機能、特に非標準の DOM 機能もサポートしているとは考えないでください。あるいは逆に、他の機能をサポートしないとも考えないでください。例えば、script 要素で onload
をサポートするブラウザは onreadystatechange
をサポートしないと考えてはいけません。各ブラウザの動作が収束することにより、機能は追加や削除されます。また、不具合の修正も行います。これら 3 点は過去に発生しており、また今後も発生するでしょう。
従ってある機能の存在有無と別の機能の存在有無に関連はありませんので、ある機能やオブジェクトの検出結果から別のことを予測しないでください。
UA 検出を行わない
これはある機能 (ユーザエージェント (UA) 文字列内に特定の文字列が含まれていること) が別の機能の有無を暗に示すと考えられている、特に一般的な実例です。
UA 検出が必要な場合は、過去のブラウザのバージョンにのみ行う
UA 検出に頼る必要がある場合は、特定のブラウザの過去のバージョンに対して用いてください。始めに、未知のブラウザおよびあなたがテストで用いているブラウザの現行バージョンと将来のバージョン向けのデフォルトのコードパスがあります。そして、デフォルトのコードパスが特定のブラウザの過去のバージョンで動作せず、またそのコードパスで機能の欠落を検出することで問題点を発見できないときは、該当する過去のバージョンのブラウザを検出することでそのブラウザ向けのハックを追加してかまいません。
この提案において、"現行" とはあなたがテストを行った最新のバージョンのブラウザを指します。例えばあなたのデフォルトのコードパスが Firefox Aurora で適切に動作するが、Firefox Beta や最新の release 版では不具合があるためにコードが動作しない場合は、テストを行った Aurora の Firefox バージョン番号を "現行" とみなし、一般向けに公開されていないものであっても Beta のバージョンを "過去" のバージョンと考えてください。
異なるブラウザ向けに分離したコードパスはむやみに作成しない
関係のあるコードパスの一つがすべてのブラウザで正しく動作するのに、わざわざオブジェクト検出や UA 検出に基づいて異なるコードを実行することは行わないでください。各ブラウザの動作がお互い収束するように変更され、そのために代替のコードパスを設定していたあなたのサイトが正常に動作しなくなってしまう可能性があります。
テストの実施
すべての主要なエンジンについてテストを行う
コードは少なくとも Firefox、Chrome または Safari (これらは同じ WebKit エンジンを基にしているため)、Opera、Internet Explorer でテストを行ってください。すべての現行ブラウザや未知のブラウザ向けに単一のコードパスを持つためこの提案に従えば、そのコードパスがすべての主要なエンジンで動作することをテストすることで、コードが将来にわたって動作する可能性がとても高くなります。
時々、各ブラウザがある機能を若干異なる形で実装します。主要なエンジンすべてで動作する単一のコードパスが得られた場合は、あなたが使用している機能の動作は各ブラウザ間で既に収束していることを意味します。一方、各ブラウザの動作が完全には収束していない場合は、どのエンジンの標準動作を支持するかが判明することに関係なくコードが動作します。
ブラウザ独自の機能や接頭辞
現行あるいは将来のバージョンのブラウザを目標にするハックを行わない
これは、現在ある不具合間の相関関係が将来の不具合間の相関関係を暗に示すと考えられている一般的な事例です。現行バージョンでは解決している不具合に関するハックを、過去のバージョンのブラウザに対して適用することは問題ありません。ブラウザが不具合 X を修正すると、不具合 X が存在するリリースすべてには不具合 Y もあることが確実にわかり、不具合 X が存在することを不具合 Y の回避策の適用基準として用いることができます。
この提案において、前出の UA 検出でのアドバイスのように "現行" とはあなたがテストを行った最新のバージョンのブラウザを指します。
最新の非標準機能に依存することを避ける
接頭辞ありの機能であっても、それを使用することは危険です。仕様書の進展に伴い、ブラウザの接頭辞ありの実装が仕様書に追随して変更されることがあります。またその機能が標準化されると、接頭辞ありのバージョンは削除されるでしょう。
接頭辞が付加された非標準の機能は、実験やフィードバックを行うためにブラウザの開発者が提供しているものであり、一般に展開することを意味していません。これらの機能を使うことを選択した場合は、機能の変更に伴って頻繁にサイトの更新が必要であることを覚悟してください。
(標準化されていても) 広く実装されていない最新機能を用いる際は縮退処理のテストを行う
あなたが用いている機能を実装していないブラウザ でどう動作するか (そのようなブラウザを Web サイトの業務で日常使用していない場合は特に)、必ずテストを行ってください。
ベンダー接頭辞が付加されている機能は、過去のバグが多いバージョンを目的とする場合を除き使用しない
ベンダー接頭辞が付加されている機能は、その動作が将来変更されるかもしれません。ブラウザがある機能を接頭辞なしで公開しても、利用可能であれば接頭辞なし版を常に使用するようにすることで、過去のリリース向けに接頭辞あり版を使用することができます。良い例として、make-it-pretty
プロパティの "sometimes"
値について接頭辞あり版とは異なる動作を接頭辞なし版に実装して公開した、-vnd
CSS 接頭辞を用いるブラウザベンダー向けの記述を示します:
<style> .pretty-element { -vnd-make-it-pretty: sometimes; make-it-pretty: sometimes; } </style>
上記の例で、規則中の宣言の順番は重要です。接頭辞のないものは、最後に置くことが必要です。
少なくとも一つのブラウザがサポートするまで、接頭辞のない CSS プロパティや API は使用しない
何らかの機能について接頭辞なし版がある程度広くサポートされるまでは、その動作が突然変更されることがあります。特に、実際に接頭辞なし版をサポートしているブラウザがない機能は使用しないでください。接頭辞あり版の文法と完成版の文法が同じであると考えてはいけません。
良好なコード
>
の欠落を防ぐ
検証ツールを用いることがこれを確実にする方法の一つですが、あなたの Web サイト全体を検証しないとしてもすべての >
文字が置かれていることを確認してください。>
が欠落していると、後ろのタグの名前が前のタグの属性であると判断されて予期せぬ状況に陥る場合があります。これはしばらくの間は動作するかもしれませんが、仕様書でその属性に意味が与えられると動作しなくなります。以下の例は HTML5 をサポートしないブラウザでは動作しますが、HTML5 をサポートするブラウザでは動作しません:
<form action="https://www.example.com"> <input type="submit" value="Submit the form" </form>
これは input
タグで >
が欠落しているためです。
コード中で動作しない実験的な部分は残さない
何か行いたいことがあって CSS プロパティを使用してみたが効果がなかった場合、そのプロパティは削除してください。将来、予期しない動作が発生する可能性があります。