first-line

first-line

[5] ::first-line 擬似要素は、要素の最初の書式付けされた行 (formatted line) を表します >>6。

仕様書

適用対象

[16] CSS ではブロック的包含子 (block-like container) (ブロック箱、inline-block、table-caption、table-cellなど) に付加された時だけ効果を持ちます。 >>6

[17] わざわざ CSS ではという注意書きがあるのは CSS におけるレンダリングの概念に依存した説明だからなのでしょうが、ということは CSS 以外で適用可能な時はこれと違う対象に効果があるということもあり得るのでしょうね。。。

擬似要素の範囲と架空的タグ列

[7] 仕様書は ::first-line 擬似要素のはたらきを架空タグ列によって説明しています。

[8] CSS で

p::first-line { text-transform: uppercase }
... のように最初の行を大文字にするように指定してあったとすると、 HTML
<P>This is a somewhat long HTML 
paragraph that will be broken into several 
lines.</P>
... の架空タグ列は、
<P>P::first-line This is a somewhat long HTML 
paragraph that </P::first-line> will be broken into several
lines.</P>
... となります。これは例えば
THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT
will be broken into several lines. 
... のようにレンダリングされます。 >>6

[9] 擬似要素に含まれる (架空のタグに囲まれる) 範囲は、文字の大きさや利用可能な幅など様々な要因によって、 どこまでが1行目に収まるかによって変わります。したがって文書として予め1行目の範囲を確定しておくことは困難なので、 要素ではなく擬似要素として表すのですね。

[12] HTML のソースコード上の改行の位置は ('white-space: pre' などでもなければ) 関係ありません。

[37] ::before や ::after による生成内容も最初の書式付き行に含まれることがあります。 >>6

[13] 擬似要素は子要素を分断させる効果をもたらすこともあります >>6。

[14] 例えば元の HTML が

<P><SPAN class="test"> This is a somewhat long HTML
paragraph that will be broken into several
lines.</SPAN> ...</P>
... であったとしましょう。その架空タグ列は、
<P>P::first-line<SPAN class="test"> This is a
somewhat long HTML
paragraph that will </SPAN></P::first-line><SPAN class="test"> be
broken into several
lines.</SPAN> ...</P>
... のように SPAN 要素を P:first-child 擬似要素がいったん閉じて再度開かせる形となっています。 >>6 レンダリング上の行は子要素の境界とは無関係に決まるため、 SPAN 要素が行をまたがることがあり、従って ::first-line 擬似要素とは互い違いになってしまうのですが、 CSS のレンダリングは木構造を前提に規定されているので、このように調整するわけです。

[28] 利用者エージェントは架空の開始タグは最も内側のブロック水準要素のすぐ内側にあるものとして扱うべきです。 ただし CSS 2.0 までこの状況について規定していなかったので、著者はこの動作に依存するべきではありません。 >>6

[29] 例えば

<DIV>
  <P>First paragraph</P>
  <P>Second paragraph</P>
</DIV>
... の架空タグ列は
<DIV>
  <P>DIV::first-lineP::first-lineFirst paragraph</P::first-line></DIV::first-line></P>
  <P>P::first-lineSecond paragraph</P::first-line></P>
</DIV>
... です。 >>6

[18] 要素の「最初の書式付けされた行」は同じフローに属するブロック水準の子孫 (つまり浮動や位置付けによってフロー外に置かれていないブロック水準の子孫) の中に出現するかもしれません。 >>6

[19] 例えば、

<DIV><P>hoge fuga ...</P></DIV>
... の架空タグ列は
<DIV><P>DIV:;first-lineP::first-linehoge fuga</P::first-line></DIV::first-line> ...</P></DIV>
... となります。

[23] table-cell や inline-block の最初の行は、先祖の最初の書式付けされた行としては扱われません。 >>6

[24] inline-block はそれ全体が行に含まれているので、 inline-block 内の最初の行だけではなく全体が (更に弟が inline-block と同じ行にあればそれも) ::first-line の後にあるものとして扱われます。 'inline-table' も同様です。

[25] table-cell はそれが 'display: table' に含まれていれば行の一部となっているわけではないので、 ::first-line には含まれません。 ::first-line に相当する部分に 'table' があるなら、 ::first-line は存在しません。 'table-caption' でも同様です。

[26] 最初の書式付けされた行は空の行となることもあります。 >>6

[27] 例えば、

<p><br>hoge
... の最初の行は br までの空の行です。

[35] 空要素で行が存在しないときには ::first-line 擬似要素も作られないようです。

[36] >>27 の例のように行はあるけど空の時は ::first-line 擬似要素は存在していそうですがよくわかりません。

[33] ::first-line 擬似要素の処理モデルに関する規定は全体的に曖昧です。

継承

[10] 継承は本当の要素からその子である擬似要素へと行われます。

[11] >>8 の例では、架空タグ列から想定される架空の文書木から想起される通り、 P 要素から P::first-line 擬似要素へと継承されます。

[32] ::first-line 擬似要素の子供に当たる要素は、 :first-line 擬似要素に適用可能な特性のみそこから継承し、 それ以外は本来の親要素から継承します。 >>6

[15] >>14 で前半部分の継承は P → P::first-line → SPAN と擬似要素をまたがる形になります。

レンダリング

[30] ::first-line 擬似要素はおおむね行内水準要素と同様に機能します。 >>6

[31] 次の特性がこの擬似要素に適用されます。 >>6

[34] ::first-line 擬似要素に対するスタイルの指定によって ::first-line に含まれる範囲が変化してしまうこともありそうですが、 どう計算するのでしょう。。。

歴史

CSS1

[45] >>44 で擬似クラスとして追加されました。 (当時は擬似要素はありませんでした。)

[43] CSS1中核では特性の一部または全部を無視してもよいとされていました。

CSS2

実装

[1] :first-line 疑似要素が文書木上の子要素を分断させる場合 (>>13)。

[2] >>1 の例その1は分断させる場合で、例その2は比較用の分断させずに完全に一部である場合。