超マイナーなCSSヲタク知識を晒してみる:CSS displayプロパティ値の自動変換

これはDMM.com #2 Advent Calendar 2017 - Qiita 23日目の記事です。
昨日は @norinity1103 さんの 「パターン・ランゲージ」のワークショップを社内で実施した件 でした。
カレンダーのURLはこちら
DMM.com #1 Advent Calendar 2017 - Qiita
DMM.com #2 Advent Calendar 2017 - Qiita

自己紹介

はじめまして。DMM.com LaboのÉcouffesと申します。最近のマイブームは吉岡里帆のどんぎつねクリアファイルを30分毎に眺める事です。

はじめに

今回 Advent Calendar 参加にあたり、当初は勢い余って『超マイナーなCSSヲタク知識を晒してみる』と宣言しました。
ヲタク知識たるもの、実務に即役立つ有益な情報は積極的に除外しなくてはなりません。とはいえ、どうせ晒すなら、何かしらCSSという言語の根幹に迫るヲタ情報でありたい。そこで今回は、『W3Cの仕様書に記載されてはいるが、これまでコードレビューを重ねてきた私の経験上、世間的にあまり知られていないと思われるCSS知識』を晒してみることにします。

対象読者

  • CSSのdisplayプロパティの特性を理解されている方
  • ブロックボックス、インラインボックスの特性を理解されている方

displayプロパティ値の自動変換

早速結論から記載します。
下記の条件をいずれか一つでも満たす場合は、当該DOM要素のdisplayプロパティ値は、inline系(inline, inline-block, inline-table, inline-flex, inline-gridなど)にはならない

  1. ルート要素
  2. floatプロパティの値が、none以外
  3. positionプロパティの値が、absolute と fixed
  4. flex item(displayプロパティ値に flex が適用された要素の子要素)
  5. grid item(displayプロパティ値に gird が適用された要素の子要素)

実証方法

chromeのDevToolsを使って確かめてみてください。
1 についてはhtml要素に対して、inline系のdisplayプロパティ値を適用し、computed styleにて確認してみてください。

スクリーンショット 2017-12-20 0.07.18.png

または、下記のJSコードでも確認可能です。

const html = document.getElementsByTagName('html')[0];
html.style.display = 'inline';
// インラインスタイルのdisplayプロパティ値にsetしたはずの'inline'ではなく、'block' を返す
document.defaultView.getComputedStyle(html)['display'];

どうでしょうか?
CSSでは、

display: inline;

が宣言されていても、computed styleではinline以外のプロパティに自動変換されていることが確認できます。

次は、2をDevToolsにて確認してみます。
下記のように、span要素があります。displayプロパティは初期値のinlineが適用されています。
スクリーンショット 2017-12-20 0.14.04.png

こちらへ、

float: left;

を適用してみると:
スクリーンショット 2017-12-20 0.14.32.png

displayプロパティの値が、自動的にinlineからblockに変換されていることが確認できます。

ただし、ここで注意が必要なのは、全てのinline系のプロパティ値がblockへ変換されるわけではありません。元々のdisplayプロパティ値の特性を活かしたまま、inline特性のみが削除されるように自動変換されます。
具体的には、下記のようになります:

declaration value computed value
inline block
inline-block block
inline-table table
inline-grid flex
inline-grid grid

実際に確認してみます:

先ずは

display: inline-flex;

というinline系のdisplayプロパティ値を適用してみます。

スクリーンショット 2017-12-20 0.15.38.png

次に、floatを適用してみると、displayプロパティ値が、flexへ自動変換されたのが確認できます:
スクリーンショット 2017-12-20 0.16.02.png

3〜5についての実証も上記と同じ方法で可能なため、詳細は割愛します。

一次資料(W3C)

上記の各項目についてはW3C公式文書に記載有:
- 1~3について、Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification > 9-7 Relationships between 'display', 'position', and 'float'
- 4について、CSS Flexible Box Layout Module Level 1 > 4. Flex Items
- 5について、CSS Grid Layout Module Level 1 > 6.1. Grid Item Display

また、displayプロパティ値が生成する『ボックス』という、より根源的な視点から、inline値へ自動変換が行われる点についての詳しい説明文書は下記に記載有:
CSS Display Module Level 3 > 2.7. Automatic Box Type Transformations

この知識の活用どころ

特にありません。
強いてあげれば、自身がCSSを書く際や、他者のコードレビューの際に活用できます。例えば、float・絶対配置と、inline-blockが同じ宣言ブロック内に入っている場合:

.hoge {
    float: left;
    display: inline-block;
    vertical-align: middle;
    ...
}

上記のようなCSSルールセットは、散見されることが多いかと思います。
この場合は、

    display: inline-block;
    vertical-align: middle;

上記CSS宣言群はcomputed時には、inlineとしての機能は自動的に失われますので、まるごと削除可能です。
vertical-alignプロパティも、displayプロパティのinline値が生成するインラインボックスのみに有効なプロパティのため、不要になります。

最後に

HTMLやCSSは様々な職種の人が使用している言語ですが、W3CやWHATWGの公式文書までに目を通している人は割と少ないのでは無いのでしょうか?
普段何気無く使用しているHTMLやCSSという言語、もし少しでも疑問に感じる点があったら、公式文書に目を通す事で新たな発見があるかもしれません。

参考