CSS display の複数キーワード構文の使用

CSS 表示モジュールは、 CSS display プロパティの複数キーワード構文を定義しています。このガイドでは、複数キーワード構文を解説します。

メモ: 複数キーワード構文は、「2 値構文」または「複数値構文」とも呼ばれています。

display プロパティの値を変更するとどうなるのか

CSS について最初に学ぶことのひとつに、ある要素はブロックレベル、ある要素はインラインレベルである、ということがあります。これらは外部表示型です。例えば <h1><p> は既定でブロックレベルであり、 <span> はインラインレベルです。 display プロパティを使用すると、ブロックとインラインを切り替えることができます。例えば、見出しをインラインにするには次のような CSS を使用します。

css
h1 {
  display: inline;
}

display プロパティを使うと、 CSS グリッドレイアウトフレックスボックスdisplay: griddisplay: flex を設定することで使用することができます。理解する上で重要なことは、要素の display 値を変更することで、その要素の直接の子要素の整形コンテキストを変更することができるという考え方です。 display: flexdisplay: grid を使用すると、要素の子はフレックスやグリッドのアイテムとなり、グリッドまたはフレックスボックス仕様のプロパティに応答します。

しかし、グリッドとフレックスボックスが示すのは、要素には外部内部の両方の表示型があるということです。外側の表示型は、その要素がブロックレベルかインラインレベルかを表します。内側の表示型は、そのボックスの子要素がどのように動作するかを記述します。

例として、 display: flex を使用すると、ブロックレベルのコンテナーを作成し、フレックスの子を持つことになります。子要素はフレックス整形コンテキストに参加するように記述されます。 これは、 <span> — 通常はインラインレベルの要素 — に display: flex を適用すると分かります。 <span> はブロックレベル要素になります。レイアウト内の他のボックスとの関係では、ブロックレベルのものと同じように動作します。あたかも span に display: block を適用したかのようですが、子要素の動作も変更されます。

以下のライブサンプルでは、<span>display: flex を適用しています。これはブロックレベルのボックスとなり、インライン方向に利用可能なすべての空間を占有します。ここで、 justify-content: space-between; を使用すると、 2 つのフレックスアイテムの間にこの空間を入れることができます。

インラインフレックスコンテナーを作成することができます。 inline-flex という単一の値を使ってフレックスコンテナーを作成すると、インラインレベルのボックスとフレックスの子が作成されます。この子はブロックレベルコンテナーのフレックスの子と同じように動作します。唯一変わったことは、親がインラインレベルボックスになったということです。したがって、他のインラインレベルのものと同様に動作し、ブロックレベルのボックスのように完全な幅(またはインライン軸のサイズ)を取りません。つまり、次のようなテキストがフレックスコンテナーと一緒に表示される可能性があります。

グリッドレイアウトで作業する場合も同様です。 display: grid を使用すると、ブロックレベルのボックスが表示され、直接の子にはグリッド整形コンテキストが作成されます。 display: inline-grid を使用すると、インラインレベルのボックスが作成され、子要素にグリッド整形コンテキストが作成されます。

複数キーワードの構文の使用

上記の説明からわかるように、 display プロパティには大きな力があります。ページ上の他のボックスとの関係でブロックレベルかインラインレベルかを示すだけでなく、それが適用されているボックス内の整形コンテキストも示します。この動作をよりよく説明するために、display プロパティは 2 つの値、外部と内部の値を設定することができます。元の単一値の構文も有効です。

つまり、 display: flex を設定して、フレックスの子を持つブロックレベルのボックスを作成する代わりに、 display: block flex を使用することになります。フレックスの子要素を持つインラインレベルのボックスを作成するには、 display: inline-flex の代わりに display: inline flex を使用します。

display の既存のすべての値に対応するものがあります。最も一般的なものを以下の表に示します。最も一般的なものを下の表に示します。完全なリストを見るには、 display property specification にある表を参照してください。

単一の値 複数の値
block block flow
flow-root block flow-root
inline inline flow
inline-block inline flow-root
flex block flex
inline-flex inline flex
grid block grid
inline-grid inline grid

display: block flow-root と display: inline flow-root

これらの新しい値が CSS レイアウトの明確化にどのように役立つかについて、表にあるあまり馴染みがないと思われる値について見てみましょう。複数キーワードの display: block flow-root は、単一の値 display: flow-root に対応します。この値の唯一の目的は、新しいブロック整形コンテキスト (BFC) を生成することです。 BFC は、ボックスの中にあるものがボックスの中に留まり、ボックスの外にあるものがボックスの中に侵入できないことを保証します。

以下の例では、 2 つの <p> 要素があり、そのうち 1 つは <div> の中にあって、どのように display の値が整形コンテキストに影響するかを表しています。 デモコントロールのある最初の <div> 要素は表示していないので、その後に続く要素に集中します。 注目すべき要素は「親」、「子」、「兄弟」の <div> 要素と <p> 要素で、これらの要素は ID によって区別することができます。

このレイアウトで注目すべき点は、親要素と子要素の間にコンテンツがないことと、子要素に上マージンが適用されていることです。 上マージンが効果的に子要素を親要素内に押し下げると思うかもしれませんが、代わりに起こるのはマージンの相殺と呼ばれる現象です。 この場合、子要素のマージンは親の外接ボックスよりかなり上まで広がり、親要素をページのさらに下に押し下げます。 これは、子要素のボックスモデルをブラウザーの開発者ツールで検査するとわかります。

<select> 要素の選択オプションを変更して、様々な display 値の効果を確認してみてください。 任意の値と flow-root を使用すると、親の新しい整形コンテキストを作成し、子要素のマージンを親の外縁に対して相対的に配置することができ、マージンの崩れを避けることができます。 flow-rootdisplay: block flow-root を切り替えると、 1 つの値の flow-root キーワードと同じ効果を得ることができます。

css
div,
p {
  outline: 2px solid black;
  background-color: cornflowerblue;
  display: block;
  margin-bottom: 2rem;
}

#parent {
  background-color: oldlace;
  min-height: 2rem;
}

#child {
  margin-top: 4rem;
  outline: 2px dashed red;
}

#sibling {
  background-color: lavender;
}
html
<div id="parent">
  <p id="child">#child の段落(#parent の内側)です。</p>
</div>
<p id="sibling">#sibling の段落(#parent の兄弟)です。</p>

flow-root の値は、ブロックとインラインのレイアウトについて考えれば、理にかなっています。これは、通常フローと呼ばれることもあるようです。 HTML ページは新しい整形コンテキストを作成し(浮動要素やマージンが境界からはみ出さない)、コンテンツはブロックとインラインレイアウトを使用して、通常のフローで表示されます。グリッドやフレックスのコンテナーを作成すると、新しい整形コンテキスト(それぞれグリッド整形コンテキストとフレックス整形コンテキスト)も作成されます。しかし、浮動要素やマージンを含めてもブロックやインラインレイアウトを使い続けたい場合は、新しいフロールートを作成し、ブロックやインラインレイアウトでやり直すことができます。その位置から下方向は、すべて新しいフロールートの中に含まれます。

したがって、display: flow-root の 2 値構文が display: block flow-root であることは、非常に理にかなっていると言えます。ブロックレベルのボックスと通常のフローに参加する子オブジェクトを持つ、ブロック整形コンテキストを作成しているのです。対応する組である display: inline flow-root についてはどうでしょうか?これは display: inline-block を記述する新しい方法です。

display: inline-block という値は、 CSS の初期から存在しています。この値を使用する理由は、例えばナビゲーションアイテムを作成する際に、インラインアイテムを要素から離して距離を置くことができるようにするため、または以下の例のようにインライン要素にパディング付きの背景を追加したい場合です。

しかし、 display: inline-block を持つ要素は、浮動要素も含むことになります。それは、インラインレベルのボックスの中にあるすべてのものを含みます。したがって、 display: inline-blockdisplay: flow-root と全く同じですが、ブロックレベルのボックスではなく、インラインレベルのボックスで行います。新しい構文は、この値で何が起こっているかを正確に表現しています。上記の例では、 Firefox で display: inline-blockdisplay: inline flow-root に変更しても同じ結果になります。

display の古い値について

display`の単一の値は、仕様書では古い値として記述されています。上の表で示されているように、各複数キーワード版にはレガシー版への直接的な割り当てがあるので、現在のところ複数キーワード版を使用することによる利点はありません。

display の値が一つだけの場合、仕様書では、外側の値である blockinline のみを使用した場合にどうするかが説明されています。

<display-outside> の値が指定されたものの、 <display-inside> が省略された場合、その要素の内側の表示型は既定で flow になります。」

つまり、単一の値の世界での動作と全く同じです。 display: blockdisplay: inline を指定すると、ボックスの外側の表示値が変更されますが、子オブジェクトは通常のフローで続行されます。 もし、内側の値である flex, grid, flow-root のみを指定した場合、仕様書では、外側の値として block を指定するように説明されています。

<display-inside> の値が指定されたものの、 <display-outside> が省略された場合、その要素の外側の表示型は既定で block になります。ただし、 ruby は例外で既定で inline になります。」

最後に、いくつか旧来の合成済みインラインレベル値があります。

  • inline-block
  • inline-table
  • inline-flex
  • inline-grid

対応しているブラウザーがこれらを単一の値として見つけた場合、以下の 2 値版と同じように扱われます。

  • inline flow-root
  • inline table
  • inline flex
  • inline grid

つまり、単一の値を使用する既存サイトと新規サイトの互換性を維持しつつ、仕様の進化を可能にすることで、現状の状況をすべてきちんとカバーしているのです。