ブロック整形コンテキスト
ブロック整形コンテキスト (block formatting context, BFC) は、ウェブページにおける CSS の視覚的なレンダリングの一部です。ブロックボックスのレイアウトが行われ、浮動要素が他の要素と相互作用する領域です。
ブロック整形コンテキストは、以下のうちの少なくとも一つから生成されます。
- 文書のルート要素 (
<html>
) - 浮動要素 (
float
がnone
以外である要素) - 絶対位置指定の要素 (
position
がabsolute
またはfixed
である要素) - インラインブロック (
display
: inline-block
である要素) - 表のセル (
display
: table-cell
を持つ要素。これは HTML の表のセルの既定値です) - 表のキャプション (
display
: table-caption
を持つ要素。HTMLの、表のキャプションの既定値です) display
: table
,table-row
,table-row-group
,table-header-group
,table-footer-group
(つまりそれぞれ HTML の表、表の行、表の本体、表のヘッダー、表のフッターの既定値),inline-table
のついた要素によって暗黙的に生成された無名の表のセル。overflow
の値がvisible
以外であるブロック要素display
: flow-root
contain
: layout
,content
,paint
の付いた要素- フレックスアイテム (
display
: flex
またはinline-flex
である要素の直接の子要素)、フレックスでもグリッドでも表でもない場合 - グリッドアイテム (
display
: grid
またはinline-grid
である要素の直接の子要素)、フレックスでもグリッドでも表でもない場合 - 段組みコンテナー (
column-count
またはcolumn-width
がauto
ではない要素、column-count: 1
の要素も含む) column-span
: all
は、column-span: all
の要素が段組みコンテナーに含まれていなくても、常に新たな整形コンテキストを生成します (仕様変更, Chrome bug)。
整形コンテキストはレイアウトに影響を与えますが、通常はレイアウトを変更するのではなく、位置決めと浮動要素の解消のために新しいブロック整形コンテキストを作成します。これは、新しいブロック整形コンテキストを確立する要素が次のようになるからです。
- 内部の浮動要素を収めます。
- 外部の浮動要素を追いやります。
- マージンの相殺を抑止します。
メモ: フレックス/グリッドコンテナー (display
: flex/grid/inline-flex/inline-grid) は新しいフレックス/グリッド整形コンテキストを確立します。これは、レイアウト以外はブロック整形コンテキストに類似しています。フレックス/グリッドコンテナーの中に利用できる浮動子要素はありませんが、外部の浮動要素を除外したり、マージンの折りたたみを抑制したりすることはできます。
例
内部の浮動要素を収める
浮動小数点コンテンツと横に並んだコンテンツの高さを同じにします。
新しいBFC を作成する効果を見るために、これらのいくつかを見てみましょう。
以下の例では、border
が適用された <div>
の中に浮動要素があります。その <div>
のコンテンツは浮動要素の横に並んだ状態になっています。浮動要素のコンテンツは横に並んだコンテンツよりも高さがあるため、<div>
の境界線が浮動要素を貫通してしまいます。フロー内とフローの外のガイドで説明しているように、浮動要素がフローから外れたので、 <div>
の background
と border
には浮動要素はなく、コンテンツだけが保持されています。
overflow: auto
の使用
overflow: auto
を設定したり、初期値である overflow: visible
以外の値を設定すると、浮動要素を含む新しい BFC を作成することができます。これで、<div>
がレイアウトの中のミニレイアウトになります。子要素はすべてこの中に含まれます。
新しい BFC を作成するために overflow
を使用することの問題点は、overflow
プロパティが、はみ出したコンテンツをどのように処理したいかをブラウザーに指示するためのものであることです。このプロパティを純粋に BFC を作成するために使用すると、不要なスクロールバーやクリップドシャドウが返されることがあるようです。さらに、将来的に開発者が読解できない可能性もあります。なぜそのために overflow
を使用したのかがわからないかもしれないからです。もし overflow
を使用するのであれば、コードにコメントをつけて説明するとよいでしょう。
display: flow-root
の使用
より新しい値の display
を使用すると、他の問題となりうる副作用なしに、新しいBFCを作成することができます。コンテナブロックに display: flow-root
を使用すると、新しい BFC が作成されます。
display: flow-root;
を <div>
に指定すると、コンテナーの中にあるすべてのものが、そのコンテナーのブロック整形コンテキストに参加し、浮動要素が要素の下部からはみ出ることはありません。
flow-root
という値は、root
要素(ブラウザーでは <html>
要素)のように、その中にフローレイアウトのための新しいコンテキストを作成することを理解すれば、理にかなったものです。
HTML
<section>
<div class="box">
<div class="float">浮動ボックスです。</div>
<p>コンテナー内のコンテンツです。</p>
</div>
</section>
<section>
<div class="box" style="overflow:auto">
<div class="float">浮動ボックスです。</div>
<p><code>overflow:auto</code> のコンテナー内のコンテンツです。</p>
</div>
</section>
<section>
<div class="box" style="display:flow-root">
<div class="float">浮動ボックスです。</div>
<p><code>display:flow-root</code> のコンテナー内のコンテンツです。</p>
</div>
</section>
CSS
section {
height: 150px;
}
.box {
background-color: rgb(224 206 247);
border: 5px solid rebeccapurple;
}
.box[style] {
background-color: aliceblue;
border: 5px solid steelblue;
}
.float {
float: left;
width: 200px;
height: 100px;
background-color: rgb(255 255 255 / 50%);
border: 1px solid black;
padding: 10px;
}
外部の浮動要素を除外する
以下の例では、 display:flow-root
と浮動要素を使用して 2 列のレイアウトを実装しています。これは、新しい BFC を確立する通常のフロー内の要素が、その要素自身と同じブロック整形コンテキストにあるどの浮動要素のマージンボックスにも重ならないためです。
HTML
<section>
<div class="float">外部の浮動要素の大きさを変えてみてください</div>
<div class="box"><p>通常</p></div>
</section>
<section>
<div class="float">外部の浮動要素の大きさを変えてみてください</div>
<div class="box" style="display:flow-root">
<p><code>display:flow-root</code></p>
</div>
</section>
CSS
section {
height: 150px;
}
.box {
background-color: rgb(224 206 247);
border: 5px solid rebeccapurple;
}
.box[style] {
background-color: aliceblue;
border: 5px solid steelblue;
}
.float {
float: left;
overflow: hidden; /* required by resize:both */
resize: both;
margin-right: 25px;
width: 200px;
height: 100px;
background-color: rgb(255 255 255 / 75%);
border: 1px solid black;
padding: 10px;
}
inline-block で width:<percentage> を使用するよりも、この場合は右側の div の幅を指定する必要がありません。
なお、最近の CSS では、フレックスボックスの方が効率的に複数列のレイアウトを搭載することができます。
マージンの相殺を防止する
新しい BFC を作成すると、隣接する 2 つの div 間のマージンの相殺を避けることができます。
マージンの相殺の例
この例では、隣接する 2 つの <div>
要素があり、それぞれの垂直マージンは 10px
です。マージンが相殺されるため、両要素間の垂直方向のギャップは 10 ピクセルとなり、期待される 20 ピクセルにはなりません。
<div class="blue"></div>
<div class="red"></div>
.blue,
.red {
height: 50px;
margin: 10px 0;
}
.blue {
background: blue;
}
.red {
background: red;
}
マージンの相殺の防止
この例では、2つ目の <div>
を外側の <div>
で囲み、新しい BFC を作成し、マージンの相殺を防いでいます。
<div class="blue"></div>
<div class="outer">
<div class="red"></div>
</div>
.blue,
.red {
height: 50px;
margin: 10px 0;
}
.blue {
background: blue;
}
.red {
background: red;
}
.outer {
overflow: hidden;
background: transparent;
}
仕様書
Specification |
---|
CSS Display Module Level 3 # block-formatting-context |