CSS Gridが適しているレイアウト、Flexboxが適してるレイアウトを詳しく解説
CSS GridとFlexboxは、CSSで現在主流となるレイアウトのテクノロジーです。
CSS GridとFlexboxは表面的には似ているように感じるかもしれません。しかし、実際には異なるタスクに使用され、それぞれ異なるレイアウトの問題を解決します。
Flexboxが適してる場合、CSS Gridが適している場合、また両方を使用する場合、さまざまなレイアウトの問題を正しく解決する方法を紹介します。
Grid vs. Flexbox: Which should you choose?
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- ページ全体のレイアウト
- 隙間が必要なレイアウト
- 1次元と2次元のレイアウト
- ラッパー
- CSS Gridは将来、Flexboxを時代遅れにするでしょうか?
ページ全体のレイアウト
CSS Gridはコンテナベースで、Flexboxはコンテンツベースです。Flexboxのレイアウトではセル(Flexアイテム)のサイズはFlexアイテム自身で定義され、CSS Gridではセル(Gridアイテム)のサイズはGridコンテナで定義されます。
実際のコードを見ながら、詳しく説明します。
水平方向にdiv要素を配置するためのHTMLを用意しました。
1 2 3 4 5 6 |
<div class="row"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> </div> |
Flexboxを使用して、スタイルしてみます。
「flex: 1 1 auto;」で、Flexアイテム内のセルのサイズが定義されています。flexプロパティでは順にflex-grow、flex-shrink、flex-basisプロパティを設定することを省略しており、デフォルト値は「0 1 auto」です。
.rowのdiv要素はFlexコンテナで、そこでアイテムのサイズを定義していないことに注目してください。Flexアイテムでサイズを定義しています。
参考: CSS Flexbox の各プロパティの使い方を詳しく解説
上記のコードは、下記のように表示されます。
ブラウザで表示
今度は、CSS Gridでスタイルしてみます。
1 2 3 4 5 6 7 8 9 10 11 |
.row { margin: 20px auto; max-width: 300px; display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; /* Size of items defined inside container */ } .row div { border: 1px dashed gray; text-align: center; padding: 12px; } |
このスタイルシートはFlexboxで実装したのと全く同じ見た目になります。
ここで注目すべきは、セルのサイズを定義しているのは.rowのdiv要素、つまりGridアイテムではなく、Gridコンテナであることです。
これは非常に重要な違いです。
Flexboxのレイアウトではコンテンツがロードされた後に計算されるのに対して、Gridのレイアウトではコンテンツに関係なく計算されることを示しています。
つまり、Flexboxでページ全体のレイアウトを構築することは表示が遅くなるため、避けた方がよいということです。
隙間が必要なレイアウト
CSS GridとFlexboxの大きな違いは、CSS Gridにはgrid-column-gapを使用してGridアイテムに隙間を作ることができることです。Flexboxには隙間のためのプロパティはありません。
隙間を使ったレイアウト
Flexboxで同様の結果を得るには、paddingとネストされたコンテナを使用するか、Flexコンテナの幅を広げてjustify-contentを使用する必要があります。
いずれは、CSS Box Alignment Module 3に用意されているマルチカラムのcolumn-gapプロパティを利用できるようになるかもしれません。
1次元と2次元のレイアウト
1次元とは一方向(横行か縦列のいずれか)に配置することで、2次元とは二方向(横行と縦列)に配置することです。これはtableレイアウトの時代からあるコンセプトで、CSS GridもFlexboxもこのコンセプトに基づいています。
1次元に要素を配置するのはFlexboxが適しています。そして2次元に要素を配置するのはCSS Gridが適しています。
Flexboxは1次元、CSS Gridは2次元、と覚えておいてもよいでしょう。よく使用される1次元のレイアウトを見てましょう。
1次元のレイアウト
HTMLはリスト要素を使用しました。
1 2 3 4 5 6 7 8 |
<ul class="social-icons"> <li><a href="#"><i class="fab fa-facebook-f"></i></a></li> <li><a href="#"><i class="fab fa-twitter"></i></a></li> <li><a href="#"><i class="fab fa-instagram"></i></a></li> <li><a href="#"><i class="fab fa-github"></i></a></li> <li><a href="#"><i class="fas fa-envelope"></i></a></li> <li><a href="#"><i class="fas fa-rss"></i></a></li> </ul> |
Flexboxでリストの各アイテムを1次元(横行)に配置します。
justify-contentプロパティは、Flexコンテナの余分なスペースがFlexアイテムにどのように分配されるかを決定します。space-aroundはFlexアイテムが均等に配置されるようにスペースを分配します。
参考: CSS Flexbox の各プロパティの使い方を詳しく解説
続いて、よく使用される2次元のレイアウトを見てましょう。
2次元のレイアウト
このレイアウトは、単一の行または単一の列で実装することはできません。複数の行と列が必要です。2次元のレイアウトなので、CSS Gridで実装します。
1 2 3 4 5 6 |
<div class="container"> <header>Header</header> <main>Main</main> <aside>Aside</aside> <footer>Footer</footer> </div> |
CSSは下記のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
.container { max-width: 800px; margin: 2em auto; display: grid; grid-template-columns: 3fr 1fr; grid-template-rows: repeat(3,auto); grid-gap: 1rem; } .container header { grid-area: 1/1/2/3; } .container main { grid-area: 2/1/3/2; } .container aside { grid-area: 2/2/3/3; } .container footer { grid-area: 3/1/4/3; } .container > * { background-color: #ddd; padding: 1rem; } |
grid-template-columnsプロパティで2つの列を作成し、grid-template-rowsプロパティで3つの行を作成しています。repeat()関数で、3つの行の高さを作成します。
Gridアイテム(header, main, aside, footer)の内部では、grid-areaプロパティを使用してそれぞれのGridアイテムがカバーする領域の大きさを定義します。
参考: CSS Gridの実装で必要な基礎知識、主要なプロパティと用語をくわしく解説
ラッパー
コンテナ内のアイテムの幅の合計がコンテナの幅より大きい場合、どちらのレイアウトモデルにもアイテムを新しい行に押し出すオプションがあります。しかし、その方法はそれぞれ異なります。
サンプルのレイアウトでその違いを見てましょう。
FlexboxとCSS Gridでそれぞれ6つのdiv要素を配置します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<h2>Flexbox</h2> <div class="row-flex"> <div>1 2 3 4 5 6 7 8 9 0</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> </div>
<h2>Grid</h2> <div class="row-grid"> <div>1 2 3 4 5 6 7 8 9 0</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> </div> |
FlexboxとCSS Gridのコードは、下記のようになります。