記事本文
仕様は最後まで読みましょう
IE 7 の :first-letter 擬似要素の font-size の算出や IE 7 の :first-letter 擬似要素の font-size のカスケーディングであれこれ悩んでいる IE 7 と :first-letter 擬似要素の問題ですが、はてなブックマーク - 徒栞の北村さんのはてなブックマーク - hxxk.jp - IE 7 の :first-letter 擬似要素の font-size のカスケーディングでの
:first-letter擬似要素を用いた時の"fictional tag"は http://www.w3.org/TR/REC-CSS2/selector.html#x57 にあり。/ 最後の図の"IE 7"と"Firefox や Opera"は逆のような
というコメントで再度仕様を読みました。
実は http://www.w3.org/TR/CSS2/selector.html#first-letter や http://www.w3.org/TR/CSS21/selector.html#first-letter は見てはいたんですよ。 ただ、最初の段落だけ読んで「うーんやっぱり要素ツリーのことについてはあまり触れていない ? 」と勝手に判断してその後まで読んでいないという。 最後まできちんと仕様は読みましょう、ということで。 これは私の怠慢に他ありません。
......ところで、以前も北村さんには言ったことがありますが、「これはブックマークコメントじゃなくてコメント欄で指摘してもらえるとありがたいなあ」と思う類のご指摘だと思いました。 私は被ソーシャルブックマーク状況をチェックする方法のまとめという記事を書いていることからも分かる通り、ソーシャルブックマークによるコメントでのご指摘も、 hxxk.jp 内のコメント欄のご指摘も同じように汲み取ります。 でも、もし同じような疑問を持っていて IE 7 の :first-letter 擬似要素の font-size のカスケーディングに辿り着いた方がいらっしゃって、かつブックマークコメントのことを知らない、あるいはそこまで気が付かないというケースがあるかもしれません。 記事を読んでの感想やメモのための要約だったらともかく、指摘や助言に類するものは直接コメント欄に書いてもらった方がありがたいなあ......と贅沢なお願いをしてみます。
:first-letter 擬似要素の要素ツリー
個人的なやりとりはさておき、示された仕様の部分を見てみましょう。
<P> <SPAN> <P:first-letter> T </P:first-letter>he first </SPAN> few words of an article in the Economist. </P>Note that the :first-letter pseudo-element tags abut the content (i.e., the initial character), while the :first-line pseudo-element start tag is inserted right after the start tag of the element to which it is attached.
これが CSS2 の Selectors - The fictional tag sequence is: の仕様で、次に引用するのが CSS 2.1 の Selectors - The fictional tag sequence is: の仕様です。
<P> <SPAN> <P:first-letter> T </P:first-letter>he first </SPAN> few words of an article in the Economist. </P>Note that the :first-letter pseudo-element tags abut the content (i.e., the initial character), while the :first-line pseudo-element start tag is inserted right after the start tag of the block element.
「その :first-letter 擬似要素が与えられた要素の開始タグの直後」か「ブロックレベル要素の開始タグの直後」かという表現の違いがありますが、 CSS2 も CSS 2.1 も 「元となる要素の開始タグの直後に :first-letter 擬似要素の開始タグが現れる」 と示されています。
......ということはですよ、この引用した例のような構造ならば、 CSS はどのように書いているかのような
* {
font-size: 100%;
}
h2 {
font-size: 2em;
}
h2:first-letter {
color: #ddd;
font-family: Arial , Verdana , sans-serif;
}
という「ユニバーサルセレクタで font-size を指定していて、 :first-letter 擬似要素で font-size を指定していない」ようなスタイルならば、 IE 7 のようにユニバーサルセレクタにマッチしてその font-size を適用する方が正しい実装で、 Firefox や Opera のように勝手に (?) h2 要素にマッチさせて font-size: 2em; としてしまう方が変な実装、ということになるのでしょうか ?
図にしてみようの補足
図にしてみようで作ってみたツリー図ですが、説明が足りなかったみたいでした。 まず説明する前に同じ図を掲載しますね。 使い回しとか言わない。
- IE 7
-
- Firefox や Opera
-
これは図の中で垂直方向に並んでいる要素は、より下の要素は上の要素の子要素になっていることを表しています。 また、同じ要素を親に持ち、水平方向に並んでいる要素はより左の方の要素が HTML 中で先に現れることを表しています。 図の元にした HTML ソースコードに、更に :first-letter 擬似要素を展開したと仮定して表すと
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head profile="http://purl.org/net/ns/metaprof">
<title>MOMENT</title>
</head>
<body>
<h1>MOMENT</h1>
<div class="section entry" id="entry-1650">
<h2><h2:first-letter>2</h2:first-letter>006-10-19T12:15:21+09:00</h2>
<p>む、とあるメールで IE7 の正式版リリースの報せが。やっぱりもう出ちゃったのかあ......</p>
</div>
</body>
</html>
となりますが、図では head 要素や div 要素を抜いてしまっていたため、逆に分かり辛くなっていました。 そこで、もう一度図を作り直してみました。
- IE 7
-

- h2:first-letter 要素での font-size の指定が無ければ、 h2 要素にて font-size が指定されていてもユニバーサルセレクタにマッチしてその font-size を適用する。
- h2:first-letter 要素にて
font-size: 150%;やfont-size: 2em;の指定があれば、 h2 要素を親要素として、その font-size の値を元に値を算出する。
- Firefox や Opera
-

- h2:first-letter 要素での font-size の指定が無く、 h2 要素にて font-size が指定されていれば、 h2 要素の font-size を適用する。 ( h2 要素でも font-size の指定が無ければ、ユニバーサルセレクタにマッチしてその font-size を適用する。 )
- h2:first-letter 要素にて
font-size: 150%;やfont-size: 2em;の指定があれば、 h2 要素を親要素として、その font-size の値を元に値を算出する。
これでどうでしょう ? 要するに、 IE 7 は h2:first-letter 擬似要素を h2 要素の独立した子のノードとして扱うのに対し、 Firefox や Opera は h2:first-letter 擬似要素は h2 要素と同じノードとして扱いつつも、プロパティの継承の場合は子のノードとして扱っているような感じです。
各ブラウザの擬似要素の取り扱い
......ここまで考えて気付いたのですが、 :before 擬似要素や :after 擬似要素によって生成される内容 (Generated content と呼び、 CSS2 ではhttp://www.w3.org/TR/CSS2/generate.html に、 CSS 2.1 では http://www.w3.org/TR/CSS21/generate.html にて仕様が示されています。 ) は基本的に元の要素と同じプロパティを適用するんですよね。
The :before and :after pseudo-elements inherit any inheritable properties from the element in the document tree to which they are attached.
For example, the following rules insert an open quote mark before every Q element. The color of the quote mark will be red, but the font will be the same as the font of the rest of the Q element:
q:before { content: open-quote; color: red }
この部分は CSS2 でも CSS 2.1 でも同じ文章ですので、とりあえず CSS 2.1 の方から引用しました。 「この例ではあらゆる q 要素の前に open-quote の引用符を挿入する。 引用符の色は ( 明確に指定されているため ) 赤色になるが、色以外のフォント関連の要素は q 要素のフォント関連の要素のスタイル指定と同じになる。」 ということです。
これは、 q:before 擬似要素を単独のノードとして扱うのではなく、 q 要素のノードに含むということではないでしょうか ? もし q:before 擬似要素を単独のノードとして扱うのならば、 q 要素での指定に関わらず q:before 要素自体での指定、あるいはそれがなければユニバーサルセレクタでの指定が適用されるはずです。
http://hxxk.jp/common/css/hxxk005.css を例に考えてみましょう。
* {
color: #000;
}
pre {
color: #ff0;
}
という指定を pre 要素に指定しています。
( 本当は color: #ffa; なのですが、色合いを分かりやすくするためにスクリーンショット取得の時だけ変更しています。 )
これに加え、 pre 要素でソースコードの説明で紹介したテクニックで pre[title]::before 擬似要素を追加しているのですが、これには特に color を指定しておらず、またユニバーサルセレクタにて color: #000; と指定しています。
しかし、 Firefox や Opera で表示してみれば
のが分かります。
ユニバーサルセレクタの color: #f00; は適用されません。
もしかしたら、 Firefox や Opera は :first-letter 擬似要素でも同じように、 :first-letter 擬似要素にて指定が無い場合は元の要素のプロパティを適用しているのではないでしょうか ? それだと腑に落ちるのですが。 IE は 7 でも :before 擬似要素や :after 擬似要素に対応していないため、そういった流れが無く :first-letter 擬似要素は独立したノードとして扱っているのでは、と思いました。
......それだと IE 6 の表示結果の説明がうまくつきませんが、もうそこまで考えたくはありません。
3 日間のまとめ
- IE 7 は :first-letter 擬似要素を独立したノードとして扱う。仕様のサンプルを見ても別に問題がある挙動ではなさげ。
- Firefox や Opera は :before 擬似要素や :after 擬似要素の扱いと同じように、 :first-letter 擬似要素でも元の要素のプロパティを適用する。これはちょっと微妙な挙動 ?
- IE 6 の挙動はよく分からない。
- CSS を書く前に読んでもらいたいことでユニバーサルセレクタによるスタイルのリセットを紹介していますが、よく考えてリセットしないと思わぬ影響が出る。まあ擬似要素にて何らかのスタイル指定があれば問題は無いので、リセットを行う場合は各セレクタの宣言ブロックをなるべくきちんと書くようにした方が良いでしょう。
- IE 7 は結局 :before 擬似要素 / :after 擬似要素に対応しなかったなあ。対応していてくれれば色々と便利だったのに。 ( 3 日間の話にはあまり関係ないけど書いておきます。 )
- この内容は某プロジェクトに使うために色々検証していたのですよ。でなきゃこんなにみっちり時間かけません。ということで「記事書いている暇があったら~」と思っていそうな某グループの数名の方はご了承下さい。



