HTML の先頭に書く DOCTYPE (文書型宣言) は、ただの決まり文句ではありません。ブラウザーは DOCTYPE を見て、ページをどの「レンダリングモード」(表示の仕方) で扱うかを決めています。古い Internet Explorer (IE) の時代には、DOCTYPE の書き方ひとつで表示が大きく崩れることがあり、IE8 からは X-UA-Compatible という独自の指定も加わって、さらに複雑になりました。ここでは、その仕組みと今の書き方をまとめます。
3 つのレンダリングモード
ブラウザーには、おおまかに次の 3 つの表示の仕方があります。
- 標準モード (standards mode): CSS の仕様どおりに表示する
- 互換モード (quirks mode): 仕様が固まる前の、古いブラウザーの表示をまねる
- ほぼ標準モード (almost standards mode): 標準モードとほとんど同じ。表のセルの中に置いた画像の、上下のすき間の扱いだけが古い表示に合わせてある
HTML の仕様では、それぞれ no-quirks mode、quirks mode、limited-quirks mode と呼ばれています。
互換モードがあるのは、すべてを仕様どおりの表示に切り替えると、それまでに作られたページが崩れてしまうからです。そこでブラウザーは、「DOCTYPE が無い、または古い書き方のページは昔の表示、きちんとした DOCTYPE があるページは仕様どおりの表示」と切り替えることにしました。この仕組みは DOCTYPE スイッチと呼ばれます。
古い IE で起きていたこと
IE の互換モードは、IE5 のころの表示をまねるものでした。いちばん大きな違いは、ボックスの幅の計算です。標準モードでは width は中身の幅で、padding と border はその外側に足されます。IE の互換モードでは、width に padding と border まで含めて計算していました。
.box {
width: 200px;
padding: 10px;
border: 5px solid #333;
}
/* 標準モード: 見た目の幅は 200 + 10 × 2 + 5 × 2 = 230px */
/* IE の互換モード: 見た目の幅は 200px (中身の幅は 170px) */
どちらのモードになるかの条件はわかりにくく、意図せず互換モードになることがよくありました。
- DOCTYPE を書かない
- HTML 4.01 Transitional の DOCTYPE で、DTD の URL を省く
- IE6 で、XHTML のページの先頭に XML 宣言 (
<?xml version="1.0" encoding="UTF-8"?>) を書く - IE で、DOCTYPE より前にコメントを書く
特に XML 宣言は、XHTML では書くのが正しいとされていたため、正しく書いたつもりで IE6 だけ表示が崩れる、ということが起きていました。
IE8 からの X-UA-Compatible
IE8 では、標準モードの表示が IE7 から大きく変わりました。IE7 に合わせて調整したページが IE8 で崩れないように、IE8 は「ドキュメントモード」という考え方を取り入れ、どの版の表示の仕方を使うかをページの側から指定できるようにしました。それが X-UA-Compatible です。
<!-- IE7 の標準モードと同じ表示にする -->
<meta http-equiv="X-UA-Compatible" content="IE=7">
<!-- その IE で使える、いちばん新しい表示の仕方にする -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
IE=7 は DOCTYPE に関係なく IE7 の標準モード、IE=EmulateIE7 は DOCTYPE スイッチに従って IE7 の標準モードか互換モード、IE=edge はその IE の最新のモード、という意味です。同じ指定は HTTP のレスポンスヘッダーでも送れました。meta 要素で書くときは、head の中で、title とほかの meta 以外の要素より前に置く必要がありました。
さらに IE8 以降には、利用者がボタンで切り替える「互換表示」もありました。互換表示にすると IE7 に近い表示になるため、同じ IE8 でも人によって見え方が違う、ということが起きました。開発者ツールでモードを切り替えながら表示を確かめるのが、このころの定番の作業でした。
今はどうするか
Internet Explorer はサポートが終わっており、今のブラウザーは X-UA-Compatible を見ません。新しく作るページに書く必要はありません。HTML の仕様でも、書くなら content="IE=edge" だけが認められていて、ブラウザーは無視することになっています。
DOCTYPE は、次のように 1 行目に <!doctype html> と書くだけで十分です。大文字・小文字は区別されません。この DOCTYPE なら、今のブラウザーでも古い IE でも標準モードになります。その前には何も書かないでください。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ページの題名</title>
</head>
<body>
<p>本文</p>
</body>
</html>
互換モードは、今のブラウザーにも古いページのために残っています。互換モードで表示すると、単位を書かない長さ (width: 100) を px として扱う、# の無い色の指定を受け付ける、高さのパーセント指定の計算が違う、といった違いが出ます。DOCTYPE を書き忘れたページで「CSS が思ったとおりに効かない」ときは、まずモードを疑ってみてください。
なお、width に padding と border を含める計算は、今は box-sizing: border-box で、意図して選べます。
モードを確かめる
今のページがどのモードで表示されているかは、開発者ツールのコンソールで document.compatMode を見るとわかります。
// 標準モードとほぼ標準モードでは "CSS1Compat"、互換モードでは "BackCompat"
console.log(document.compatMode);
iframe で読み込んだページは別の文書なので、モードもそれぞれ別に決まります。親ページが標準モードでも、中のページの DOCTYPE が無ければ、そのページだけ互換モードになります。
まとめ
- ブラウザーは DOCTYPE を見て、標準モード・ほぼ標準モード・互換モードを切り替える
- 古い IE の互換モードは IE5 のころの表示をまね、ボックスの幅の計算まで変わった
- IE8 以降は X-UA-Compatible で表示の版を指定できたが、今のブラウザーには不要
- 今は 1 行目に
<!doctype html>を書き、その前には何も書かない - モードは
document.compatModeで確かめられる