本シリーズは、エンジニアとしての実力不足を常日頃から感じている私が、仕様書(日本語訳)を読み、得た知識をアウトプットしていくためのものとなっております。
今回読んだ章
前提
※自分が理解しやすいようにコテコテに意訳してます
ブロックと要素の違い
本章では、「ブロック」と「要素」の2フレーズが明確に使い分けられています。
※ここではそんなに深く考えなくて良いような気も
ブロック
ページ上にレンダリングされる実態。
要素
ブロックを生成するための存在。実態はない。
ビューポートとキャンバス
キャンバス
HTMLなどの文書の描画領域。
ビューポート
ユーザーは、ユーザーエージェント(ほぼブラウザ)が提供するビューポートを介してキャンバスを閲覧することができる。
ビューポートがキャンバスの面積よりも小さい場合、スクロールバーが現れる。
置換要素と内在次元
置換要素
<img>とか<iframe>とか<embed>とか。 CSSの整形モデルとは独立して表現される要素のこと。
内在次元
要素自身によって定義された幅と高さ(非CSS指定)。
<img width="300" height="300">みたいなやつ。
内在次元は、置換要素のみが持てる。(例えば、div要素は非置換要素なので、widthやheight属性は持てない)
また、周囲の要素に影響されない。
包含ブロック(頻出)
ある子要素が、位置や大きさを計算する際の基準となるブロック。
例えば、CSSでwidth:100%を指定した場合、 要素幅を包含ブロック幅の100%にする 、という意味になります。(親要素の100%、と理解していましたが、厳密に言うと違うわけですね)
本題
視覚整形モデルって?
ブラウザがどのようにHTMLをレンダリングするか、の決め方
レイアウトの決まり方
以下の四つによって決まる
- ボックスの次元(paddingとかmarginとかの話)と種類(つまり、 displayプロパティ )
- ボックスの位置決めスキーム(つまり、 positionプロパティ )
- DOMツリーでの要素間の関係(HTMLで後に書かれた要素が下に追加されていく、というような話)
- その他外部情報(ビューポートサイズ、画像の内在次元など)
displayにまつわる話
ブロックレベルボックス
外(親)から見た時にブロックに見える=ブロックレベルボックス
ブロックレベルボックスを生成する要素が、ブロックレベル要素。
display:blockdisplay:list-itemdisplay:table
の時、ブロックレベル要素になる。
(追記:display:flexやdisplay:gridもブロックレベル要素になります。が、ブロックコンテナ要素にはならず、それぞれフレックスコンテナ、グリッドコンテナを生成します)
ブロックコンテナボックス
箱の内側がブロック。親としてブロック=ブロックコンテナボックス
ブロックコンテナボックスを生成する要素が、ブロックコンテナ要素。
display:blockdisplay:list-itemdisplay:inline-block
の時、ブロックコンテナ要素になる。
※ 全てのブロックコンテナボックスがブロックレベルボックスであるとは限らない。
例えばdisplay:tableの場合は、ブロックレベルボックスだけど、ブロックコンテナボックスではない、ということになる
ブロックボックス
ブロックレベルボックスであり、かつブロックコンテナボックスである場合、ブロックボックスと呼ぶ。
display:blockの場合、自身も子要素もブロックレベルとして扱うため、ブロックボックスということができる。
……この辺、display:blockにすると、(一義的な)ブロック要素になるんだーという浅い理解しか持っていなかったのですが、実際には二つの性質を併せ持つような設定だったのですね。
インラインレベルボックス
外(親)から見た時にインラインに見える=インラインレベルボックス
インラインレベルボックスを生成する要素が、インラインレベル要素。
display:inlinedisplay:inline-tabledisplay:inline-block
の時、インラインレベル要素になる。
インラインボックス
外側も内側もインラインに見えるボックスを、インラインボックスと呼ぶ。
display:inlineなどは、インラインボックスである。
……とまあ、文字だけで見ると、少し分かりにくいかもしれません。
この辺のボックスの話は、display:inline-blockを例にとると理解しやすいです。
↓
分割不可能なインラインレベルボックス(atomic inline-level boxes)
前述の説明を見てお気づきになった方もいるかもしれませんが、display:inline-blockはブロックコンテナボックスであり、インラインレベルボックスでもあります( このようなボックスを、分割不可能なインラインレベルボックス(atomic inline-level boxes) と呼びます)
↓は、その図解です。
inline-blockは、外(親)から見たらinlineで、中(子)から見たらblock、と言うことです。
だからこそ、以下のようなプロパティ指定が有効になります。
See the Pen Untitled by tsukaD (@gqzoomig-the-lessful) on CodePen.
inline-block指定がされている.child要素は、親の側から見てinlineのため、.container要素のtext-align:centerが効いており、かつブロックコンテナのため、.child要素自身のwidth指定も効いている、と言う状態です。 これが例えばdisplay:blockであれば、中央寄せが効かなくなるし、display:inlineにすれば今度はwidth指定が効かなくって視覚的に消滅します。
positionにまつわる話
positionプロパティによって、どのCSS位置アルゴリズムを使用するかが決まります。
通常フロー
positionの話を始める前に、まずCSSにおける「通常フロー」の概念を理解しておく必要があります。
フローとは、ページにボックスがレイアウトされる際に従うルールのことです。
通常フローではその中でもデフォルトのルールのこと。ブロック要素は上から下に、インライン要素は左から右へ配置されていきます。
そして、position指定によっては、この通常フローから外れるといったことが起こります。そうなると、通常フローで置かれたボックスを無視して配置が行われる、などの事が起こります。
position: static
通常ボックスであり、位置も通常フローに従って決まる。top,right,bottom,left(以下inset)は適用されない。
position: relative
自身のレイアウトと言う観点から言えば、inset指定のできるposition: static。
通常フローで、相対配置。つまり、
-
最初に通常フローに従って、「本来この要素はここに置かれる」と言う基準位置が最初に決まる
-
通常位置から、
insetの分だけズレる
と言う流れでレイアウトが決定される。
なお、insetによってズレるのはあくまで見た目だけで、通常フローの中では元の位置にある扱いのため、次に差し込まれるボックスのレイアウトには影響しない。
position: absolute
ボックスの位置はinset指定によって決まる。insetの基準は包含ブロックになる。
なお、position:absoluteの要素では、通常と異なり、最も近い位置指定された祖先要素が包含ブロックとなる。
絶対配置。また、通常フローの範囲外になるため、以降の兄弟のレイアウトに影響せず、マージンの相殺も起こらない。(マージンの相殺についてはこちらの記事で分かりやすく説明されています)
position: fixed
位置計算自体はabsoluteと同じ。基準を包含ブロックにするか、ビューポートにするかの違い。
固定配置(絶対配置の下位区分らしい)
注記
一部、執筆者がどうしても理解できなかった箇所や、重要性があまり高くないと思った(と言うより活用の仕方がよくわからなかった)箇所は、本記事には載せていません。
またCSS2.2時点の仕様書の日本語訳を扱っているため、position: stickyなど比較的新し目の仕様の話はカバーできておりません。
100%の理解を目指される方には、ご自身で仕様書本体を読まれることをお勧めします。
