視覚整形モデル
CSS の視覚整形モデル (visual formatting model) は、ユーザーエージェントが文書ツリーをどのように受け取り、視覚メディア用に処理して表示するかを説明するものです。これには、コンピューター画面のような連続メディアと、ブラウザーの印刷機能によって印刷された本や文書のようなページメディアが含まれます。情報の大部分は、連続メディアとページメディアに等しく適用されます。
視覚整形モデルでは、文書ツリーの各要素は、モデルに応じてゼロ個以上のボックスを生成します。これらのボックスのレイアウトは、次のようにして制御されます。
- ボックスの寸法と種類
- 位置決定方法 (通常フロー、浮動、絶対位置指定)
- 文書ツリー内の他の要素
- 外部情報 (ビューポートの寸法、画像の固有の寸法、など)
視覚整形モデルに関する情報の多くは CSS2 で定義されていますが、様々なレベル 3 の仕様書ではこの情報が追加されています。仕様書を読む際には、 CSS2 で定義されているモデルが参照されていることが多いので、他のレイアウト仕様書を読む際には、 CSS2 で定義されているモデルとそれを説明するために使用されている用語を理解しておくことが重要です。
この文書では、モデルを定義して関連する用語や概念をいくつか紹介し、より詳細な情報を説明している MDN のより具体的なページへのリンクを紹介します。
ビューポートの役割
連続メディアでは、ビューポートはブラウザーのウィンドウから見える領域です。ユーザーエージェントはビューポートの寸法が変更されたときに、ページのレイアウトを変更することがあります。 — 例えば、ウィンドウの寸法を変更した場合や、モバイル端末の向きを変更した場合です。
ビューポートが文書の寸法よりも小さい場合、ユーザーエージェントは文書の表示されていない部分へスクロールする方法を提供する必要があります。もっともよくあるのは、横書きで、上から下へ書く言語の場合、ブロック方向のスクロールです。しかし、インライン方向のスクロールを設計する必要がある場合もあるかもしれません。
ボックスの生成
ボックスの生成は CSS の視覚整形モデルの一部で、文書内の要素からボックスを作ることです。生成されたボックスは様々な種類を持ち、視覚整形モデルに影響します。生成されるボックスの種類は CSS の display
プロパティによって決まります。
当初 CSS2 で定義された display
プロパティは、 CSS Display Module Level 3 で拡張されました。これに加え、 display にまつわる用語の一部が CSS2 から何年にもわたって更新され明確化されました。
CSS はソース文書を読み取り、キャンバスにレンダリングします。これを行うために、中間的な構造であるボックスツリーを生成し、レンダリングされる文書の書式構造を表現します。ボックスツリー内のそれぞれのボックスは、キャンバス上の空間や時間において対応する要素 (または擬似要素) を表現しており、ボックスツリー内のテキストは対応するテキストノードの内容のように表現します。
それから、それぞれの要素について、 CSS はその要素の display
プロパティの値に応じてゼロ個以上のボックスを生成します。
メモ:
ボックスはよく display の種類によって参照されます。例えば、 display: block
の要素によって生成されたボックスは「ブロックボックス」と呼ばれたり、単に「ブロック」と呼ばれたりします。ただし、ブロックボックス、ブロックレベルボックス、ボックスコンテナーはすべて微妙に異なることに注意してください。詳しくは下記のブロックボックスを参照してください。
主ボックス
要素が 1 つ以上のボックスを生成する場合、そのうちの一つが主ボックス (principal box) となります。これがボックスツリー内の子孫ボックスと生成コンテンツを含み、様々な配置方法の対象となるボックスとなります。
要素によっては、主ボックスに加えて追加のボックスを生成することがあり、例えば、 display: list-item
は複数のボックス (例えば 主ブロックボックスや子マーカーボックス) を生成します。また、値によっては (none
や contents
など) 要素やその子孫がまったくボックスを生成しなくなります。
無名ボックス
無名ボックス (anonymous box) は、ボックスに使用する HTML 要素がない場合に作成されます。このような状況は、例えば、親要素で display: flex
を宣言した場合に、その中に他の要素に含まれないテキストが直接存在する場合に発生します。ボックスツリーを修正するために、そのテキストの周りに無名ボックスが作成されます。これはフレックスアイテムとして動作しますが、対象となる要素がないため、通常のボックスのように対象を設定したり、スタイルを設定したりすることはできません。
同じことは、ブロック要素にテキストが混在している場合にも起こります。次の例では、 <div>
の中に文字列があり、文字列の中央にはテキストの一部を含む <p>
要素があります。
文字列はボックスツリーの中で3つのボックスに分割されます。段落要素の前の文字列の部分は無名ボックスに包まれ、次にボックスを生成する <p>
があり、さらに別の無名ボックスがあります。
これらの無名ボックスについて考慮すべきことは、直接の親からスタイルを継承するということですが、無名ボックスを対象にして、それらがどのように見えるかを変更することはできません。この例では、コンテナーの子を対象にするために直接子セレクターを使用しています。これは、無名ボックスは「要素」ではないので、無名ボックスを変更するものではありません。
インライン無名ボックスは、文字列がインライン要素によって分割されたとき、例えば文に <em></em>
で囲まれた区間がある場合に作成されます。これにより、文が3つのインラインボックスに分割されます。強調された区間の前の無名インラインボックス、 <em>
要素で包まれた区間、そして最後の無名インラインボックスです。無名ブロックボックスと同様に、これらの無名インラインボックスは <em>
の場合とは異なり、独立してスタイルを設定することはできず、コンテナーのスタイルを継承するだけです。
他にも無名ボックスを生成する整形コンテキストがあります。グリッドレイアウトは上記のフレックスボックスの例と同様に動作し、テキストの文字列を無名ボックス付きのグリッドアイテムに変換します。段組みレイアウトは段の周りに無名の段ボックスを生成します。これらもスタイル付けなどの対象にすることはできません。表レイアウトは適切な表構造を生成するために無名ボックスを追加します。例えば、 display: table-row
が付いたボックスがない場合、無名の表の行を追加するなどです。
行ボックス
行ボックスは、テキストの各行を包むボックスのことです。アイテムを浮動させた後に、背景色のあるブロックを続けると、行ボックスとそれを含むブロックの違いがわかります。
次の例では、浮動している <div>
の後に続く行ボックスは、浮動要素を回り込むように短くなっています。浮動したアイテムがフローから抜けるので、ボックスの背景は浮動要素の後ろを走っています。
配置の仕組みとフロー内・フロー外の要素
CSS では、ボックスをレイアウトするための配置の仕組みが 3 種類あります。 — 通常フロー、浮動、絶対位置指定です。
通常フロー
CSS において、通常フロー (normal flow) にはブロックボックスのブロックレベル整形、インラインボックスのインラインレベル整形、それにブロックレベルおよびインラインレベルボックスの相対位置指定と粘着位置指定があります。
詳しくは フローレイアウトを参照してください。
浮動要素
浮動モデルでは、ボックスは、まず通常の流れに従ってレイアウトされ、その後、流れから取り出され、ふつう左または右に配置されます。コンテンツは、フロートの側面に沿って折り返されます。
詳しくは浮動要素を参照してください。
絶対位置指定
絶対位置指定モデルでは (固定位置指定も含む)、ボックスは完全に通常フローから外され、包含ブロック (固定位置指定の場合はビューポート) を基準とした位置に配置されます。
要素が浮動要素、絶対位置指定、ルート要素のいずれかであれば、フロー外と呼ばれます。フロー外ではない要素はフロー内と呼ばれます。
詳しくはCSS 位置指定レイアウトを参照してください。
整形コンテキストと display プロパティ
ボックスは外部表示型、すなわち block
または inline
で表すことができます。この外部表示型はページ上でそのボックスが他の要素との間でどのようにふるまうかを示します。
ボックスには内部表示型もあり、これは子がどのように動作するかを示します。通常ブロックかつインラインレイアウト、または通常フローであれば、この表示型は flow
です。これは、子要素が block
または inline
のどちらかであることを示します。
しかし、内部表示型は grid
や flex
になる可能性もあり、この場合は直接の子がグリッドまたはフレックスアイテムとして表示されます。このような場合、要素はグリッドやフレックスの整形コンテキストを生成しているといいます。多くの点でこれはブロックの整形コンテキストに似ていますが、子要素は通常のフローのアイテムではなく、フレックスやグリッドのアイテムとして動作します。
ブロックレベルとインラインレベルの各ボックスの相互作用は、 display
の MDN ドキュメントで説明しています。
また、 display の特定の値については、ボックスレイアウトの観点から、これらの整形コンテキストがどのように機能するかを以下のリファレンスで説明しています。
- CSS グリッドレイアウト
- CSS フレックスボックスレイアウト
- CSS 表モジュール
- CSS リストとカウンターモジュール
独立整形コンテキスト
要素は、それを含むブロックの整形コンテキストに参加するか、独立整形コンテキストを確立するかのどちらかです。例えば、グリッドコンテナーは、その子に対して新しいグリッド整形コンテキストを確立します。
独立整形コンテキストは浮動要素を含み、マージンは整形コンテキストの境界を越えて相殺されることはありません。そのため、新しいブロック整形コンテキストを作成することで、ボックス内に浮動要素が収まるようにすることができます。このためには、display: flow-root
を新しいブロック整形コンテキストを生成したいボックスに追加してください。
次の例は、display: flow-root
の効果を示しています。黒い背景のボックスが、浮動アイテムとテキストを包み込むように見えます。編集可能な CSS から display: flow-root
を削除すると、浮動アイテムがボックスの底から突き出てしまい、アイテムが収まらなくなります。
ブロックボックス
仕様書では、ブロックボックス、ブロックレベルボックス、ブロックコンテナーのことを、あるところではブロックボックスと呼んでいます。これらはやや異なるものであり、ブロックボックスという用語は曖昧さがない場合にのみ使用すべきです。
ブロックコンテナー
ブロックコンテナーは、インライン整形コンテキストに参加するインラインレベルのボックスのみを含むか、ブロック整形コンテキストに参加するブロックレベルのボックスのみを含むかします。このため、上で説明した動作では、すべてのアイテムがブロックまたはインラインの整形コンテキストに参加できるように、無名ボックスが導入されています。要素は、ブロックレベルまたはインラインレベルのボックスを含む場合にのみ、ブロックコンテナーとなります。
インラインレベルボックスとブロックレベルボックス
これらはブロックコンテナーの内部に含まれるボックスであり、それぞれインラインレイアウトとブロックレイアウトに参加します。
ブロックボックスの場合
ブロックボックスとは、ブロックレベルボックスでありながらブロックコンテナーでもあるものを指します。 CSS の display
で説明されているように、ボックスがブロックレベルのボックスであってもブロックコンテナーにはならないこともあります (例えば、フレックスコンテナーやグリッドコンテナーになることもあります)。