7cc@はてなブログ

JavaScriptとかとか

Quirks Mode (互換モード) - document.compatMode

レンダリングモード(描画モード)とJavaScriptについて書かれているページがほとんど無いので簡単に。
JavaScriptへの影響のみを対象とする。

レンダリングモードとは

ブラウザには、古いWebページの描画(render)向けに普段と違う表示を行う機能がある。
普通の表示はStandards Compliant mode(標準準拠モード)、古い表示はQuirks mode(後方互換モード)と呼ばれる
詳しくは下記サイトを

嬉しくないことに、HTML5では別名で呼ばれるようになった。

old new(HTML5)
standards mode No-quirks mode
almost standards mode limited-quirks mode
quirks mode quirks mode

そのため仕様書ではDocument is not in quirks modeというように遠回しの説明がされている。素直に"Document is in standards mode"と書けばいいのに!
http://dev.w3.org/csswg/cssom-view/#dom-element-scrolltop

Quirksモードで表示されるサイト例

大手サイトでもQuirksモードで表示されるサイトがちらほら見られる(2013/09/07現在)

判別

プロパティ

document.compatMode

戻り値

Standards Quirks
CSS1Compat BackCompat

Compat = compatibility
BackCompat = backward compatibility

document.documentModeというのもあるがIEのみで、別に使わなくてよい(と思う)。

JavaScriptへの影響と対応

Quirks-modeではブラウザ間の互換性が損なわれる。特にIE

  • Quirksに対応する必要が無いならしない
    • メジャーなライブラリでも対応していないことが多い*1
  • StandardsとQuirks両対応する必要はない
    • ページがQuirksで表示されると分かっているなら、Quirksのみを考えればよい
    • 両対応のコードは可読性が悪い
    • 動作テスト対象が2倍になる(この負担が大きい)
  • HTMLの書き換えができるならそうする
    • 上記の通り苦労が激増するのでなるべくHTMLを修正する。

機能

  • IEで使用できる機能がIE5-6相当になる
    • IE9でもpageYOffset, addEventListener, getElementsByClassNameなどが使えなくなる
    • CSSの対応も古くなるので、element.style.opacityから透明度を操作できなくなる
  • IE以外は最近の機能も使うことができる
    • Firefoxではdocument.allが使えるようになったりもする。しかしinnerTextなどは使えないので微妙

対応

他のクロスブラウザの場合と同じ。ifで機能が使えるか調べ処理を変えるだけ。ただし戻り値が0になるケースがあるので注意。

  1. undefinedと比較する
  2. inを用いる
// この場合は undefined と比較する必要はないが
if ( document.getElementsByClassName ) // if supported -> ok

// 数字が返る場合があるのでundefinedと比較する
if ( window.pageYOffset ) // false @ page top -> NG
if ( window.pageYOffset !==  undefined ) // if supported -> ok

// あるいは in を使う
if ( "pageYOffset" in window ) // if supported -> ok

html, bodyのサイズやスクロール量が変わる

Quirksモードではbodyがドキュメントサイズの基準となり、
window.scrollBy, pageYOffsetなどwindowに関係する値が全てのブラウザでbodyと一致するようになる。

Webkitは特殊なのでややこしいが、表にするとこうなる

document FF, IE Webkit Quirks property
scrolled html body body scrollTop
size html body body scrollHeight
viewport html html body clientHeight

対応

document.compatModeを用いる
ブラウザ・バージョンの判別と違い信頼性は高い

isStandardsと変数に入れると分かりやすいと思う。
toLowerCaseは別に使わなくてよい、が万全を期して。

var isStandards = document.compatMode.toLowerCase() === "css1compat"

if(isStandards){
  // Standards
}
else{
  // Quirks
}

ブラウザ判別は行わない