JavaScriptでCSSパーサーを書くための情報を収集中(1日目)
<style type="text/css"> ... </style>
- CSS ファイルを一本化できればステキ。ブラウザ毎に書き分けるのって本来の姿じゃない。
- CSS3 の機能を古いブラウザで使えればもっとステキ。
- 古いブラウザに時間を掛けたくない。CSS のバッドノウハウなんてノーサンキュー。やりたいことが表現できればそれでいい。
- ブラウザに CSS の解釈を任せなきゃいいんじゃないか?
まずは、JavaScript で CSSパーサーを書くための情報収集からです。
わかってること
ロード済みのスタイルシートは、document.styleSheets に擬似配列として格納されています。長さは document.styleSheets.length から取得できます。
スタイルシートの各ルールは、cssRules (IE なら rules)に格納されています。
document.styleSheets[0].cssRules[0].selectorText からセレクタ("a:hover")が取り出せます。
document.styleSheets[0].cssRules[0].style.cssText から宣言("color: black")が取り出せます。
これらから、ブラウザが解釈済みの ルールセットを取り出すことができます。
ブラウザが解釈しないルールがある場合はどうなるの?
IE6 は以下の CSS をパースすると
<style type="text/css"> div > ul > li { color: pink; } </style>
document.styleSheets[0].rules[0].selectorText が、"UNKNOWN" になります。
IE6 は "E > F" といったセレクタを理解しようとしません。
この場合、document.styleSheets[0].rules[0].style.cssText は "COLOR: pink" になります。
div > ul > li { color: pink; } というルールを復元するための情報は、 document.styleSheets から失われてしまっています。
情報がロストしてんのにどうすんの?
document.getElementsByTagName("style")[0].innerHTML を見ると、本来のCSSがテキストとして残っているようです。
div > ul > li { color: pink; }
ただし、document.styleSheets[0].rules にアクセスした後では innerHTML が改変されてしまいます(document.styleSheets や length へのアクセスなら大丈夫)。
UNKNOWN { COLOR: pink }
このことから、IE で生の CSS を取得するには、rules にアクセスせず、直接 innerHTML から取得しなければなりません。
他のブラウザは大丈夫?
未知の擬似クラス(:digit)をブラウザに食べさせ、どうなるか試してみました。
:digit { color: pink; }
CASE1: cssRules または rules にアクセス後に innerHTML, innerText, textContent からルールを取り出す
Browser | innerHTML | innerText | textContent |
Firefox2 | ○ | ‐ | ○ |
Firefox3 | ○ | ‐ | ○ |
Firefox3.5 | ○ | ‐ | ○ |
Opera9.27 | ○ | ○ | ○ |
Opera9.61 | ○ | ○ | ○ |
Opera10β | ○ | ○ | ○ |
Safari4 | ○ | ○ | ○ |
Google Chrome3β | ○ | ○ | ○ |
IE6 | :unknown { COLOR: pink } | "" | ‐ |
IE7 | :unknown { COLOR: pink } | "" | ‐ |
IE8(mode7) | :unknown { COLOR: pink } | "" | ‐ |
IE8(mode8) | "" | "" | ‐ |
○ = そのまま維持されている
‐ = プロパティが存在しない
CASE2: cssRules または rules にアクセスせず innerHTML, innerText, textContent からルールを取り出す
Browser | innerHTML | innerText | textContent |
Firefox2 | ○ | ‐ | ○ |
Firefox3 | ○ | ‐ | ○ |
Firefox3.5 | ○ | ‐ | ○ |
Opera9.27 | ○ | ○ | ○ |
Opera9.61 | ○ | ○ | ○ |
Opera10β | ○ | ○ | ○ |
Safari4 | ○ | ○ | ○ |
Google Chrome3β | ○ | ○ | ○ |
IE6 | ○ | "" | ‐ |
IE7 | ○ | "" | ‐ |
IE8(mode7) | ○ | "" | ‐ |
IE8(mode8) | ○ | "" | ‐ |
開発ツール起動中 IE8(mode7) | :unknown { COLOR: pink } | "" | ‐ |
開発ツール起動中 IE8(mode8) | "" | "" | ‐ |
IE8 はデグレードしてる。⇒ IE8 の開発ツールが起動していると、何らかのタイミングで評価してしまうらしく結果が変ってしまいます。