ブロック整形コンテキスト

ブロック整形コンテキスト (block formatting context, BFC) は、ウェブページにおける CSS の視覚的なレンダリングの一部です。ブロックボックスのレイアウトが行われ、浮動ボックスが他の要素と相互作用する領域です。

ブロック整形コンテキストは、以下のうちの少なくとも一つから生成されます。

  • 文書のルート要素 (<html>)
  • 浮動ボックス (floatnone 以外である要素)
  • 絶対位置指定の要素 (positionabsolute または 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 の値が visibleclip 以外であるブロック要素。
  • display: flow-root である要素。
  • <button> 要素およびボタン型の <input> 要素で既定値の display: flow-root であるもの。
  • contain: layout, content, paint の付いた要素
  • フレックスアイテム (display: flex または inline-flex である要素の直接の子要素)、フレックスでもグリッドでもでもない場合
  • グリッドアイテム (display: grid または inline-grid である要素の直接の子要素)、フレックスでもグリッドでもでもない場合
  • 段組みコンテナー (column-count または column-widthauto ではない要素、 column-count: 1 の要素も含む)
  • column-span: all は、 column-span: all の要素が段組みコンテナーに含まれていなくても、常に新たな整形コンテキストを生成します。

新しいブロック整形コンテキストを確立する要素は、レイアウトに影響を与えるため、整形コンテキストはレイアウトに影響を与えます。

  • 内部の浮動ボックスを収めます。
  • 外部の浮動ボックスを追いやります。
  • マージンの相殺を抑止します。

要素の displayflexgridinline-flexinline-grid のいずれかに設定すると、フレックス/グリッドコンテナーとなり、新しいフレックス/グリッド整形コンテキストを確立します。これらはブロック整形コンテキストに似ていますが、フレックスコンテナーやグリッドコンテナー内では浮動ボックスを利用できないという点が異なります。ただし、これらのコンテキストでは外部浮動ボックスは除外され、マージンの相殺は抑制されます。

新しい BFC を作成する効果を見るために、これらのいくつかを見てみましょう。

内部の浮動ブロックを収める

以下の例では、borderが適用された <div> の中に浮動ボックスがあります。その <div> のコンテンツは浮動ボックスの横に並んだ状態になっています。浮動ボックスのコンテンツは横に並んだコンテンツよりも高さがあるため、<div> の境界線が浮動ボックスを貫通してしまいます。フロー内とフローの外のガイドで説明しているように、浮動ボックスがフローから外れたので、 <div>backgroundborder には浮動ボックスはなく、コンテンツだけが保持されています。

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> 要素)のように、その中にフローレイアウトのための新しいコンテキストを作成することを理解すれば、理にかなったものです。

これは、 <button> 要素とボタン型の <input> 要素の既定のレンダリングです。すなわち、ボタンは、 display の値が新しい BFC を自動的に作成しない値に設定されていない限り、新しい BFC を作成します。

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

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

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

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;
}

マージンの相殺を抑止する

新しい BFC を作成すると、隣接する 2 つの div 間のマージンの相殺を避けることができます。

マージンの相殺の例

この例では、隣接する 2 つの <div> 要素があり、それぞれの垂直マージンは 10px です。マージンが相殺されるため、両要素間の垂直方向の間隔は 10px となり、期待される 20px にはなりません。

html
<div class="blue"></div>
<div class="red"></div>
css
.blue,
.red {
  height: 50px;
  margin: 10px 0;
}

.blue {
  background: blue;
}

.red {
  background: red;
}

マージンの相殺の抑止

この例では、 2 つ目の <div> を外側の <div> で囲み、外側の <div>overflow: hidden を使用して新しい BFC を作成します。この新しい BFC は、入れ子になった <div> のマージンが外側の <div> のマージンと相殺されるのを防ぎます。

html
<div class="blue"></div>
<div class="outer">
  <div class="red"></div>
</div>
css
.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

関連情報