このページの中身

レイアウトの実装

Flexbox は中身が並びを決め、Grid は先に枠を決めて中身を置きます。列を揃えたいなら、答えは Grid です。

Flexboxが一方向の並び、Gridが行と列の両方を決めることを比較した図
図を大きく見る
図の中身を文字で読む
  • Flexbox は中身が並びを決める。Grid は先に枠を決めて中身を置く。
  • Flexbox = 一方向 Grid = 行と列
  • 幅は中身の量で決まる。数が変わっても崩れない。 中身と関係なく、列の幅が揃う。
  • 向きは row か column のどちらか一方。 要素をまたいで配置できる(2列分など)。
  • ヘッダーの並び、ボタンの列、タグの群れ。 ページ全体の骨格、カードの一覧、表組み。
  • 迷ったときの分かれ目
  • 列の幅を揃えたい Grid Flexbox で揃えるには全項目に同じ flex-basis が要る
  • 中身の量で幅を変えたい Flexbox Grid の列は先に決まるので、中身に追従しない
  • 親の幅で列数を変えたい Grid repeat(auto-fit, minmax(16rem, 1fr)) だけで折り返す
  • 親要素の列に子も揃えたい サブグリッド カードの見出し・本文・ボタンの高さが列をまたいで揃う

ひと目で#

Flexbox は中身が並びを決める。Grid は先に枠を決めて中身を置く。

Flexbox
一方向に並べる。幅は中身の量で決まる
CSS Grid
行と列を先に定義する。中身と関係なく揃う
サブグリッド
子要素が、親の列と行をそのまま使う
clamp
最小、推奨、最大を1つの関数で書く
メディアクエリ
画面の幅で分岐する
コンテナクエリ
親要素の幅で分岐する。部品が場所を選ばなくなる

使い分け#

こういうとき使うもの
列の幅を揃えたいGrid
中身の量で幅を変えたいFlexbox
親の幅に応じて列の数を変えたいGrid の auto-fit と minmax()
カードの中の見出し、本文、ボタンを、列をまたいで揃えたいサブグリッド
置く場所によって部品の形を変えたいコンテナクエリ
画面全体の骨格を変えたいメディアクエリ
文字や余白を幅に連動させたいclamp()

画面の幅か、親の幅か#

同じカード部品を、本文の広い列と脇の狭い列の両方に置くとします。メディアクエリは画面の幅しか見ないので、脇に置いても「画面は広い」と判断して横組みのまま崩れます。

同じカード部品を本文の列と脇の列に置いたとき、メディアクエリでは脇でも横組みのまま崩れ、コンテナクエリでは縦積みに落ちることを比べた図
図を大きく見る
図の中身を文字で読む
  • 同じカード部品を、本文の広い列と脇の狭い列に置いたとき
  • ✕ メディアクエリ(画面の幅を見る) ○ コンテナクエリ(親の幅を見る)
  • 画面 1280px 画面 1280px
  • 本文の列 脇の 親が広い
  • 横組みで収まる 列 横組み 縦積み
  • 脇に置いても横組みのまま。部品は「画面は広い」と判断する 親が狭ければ縦積みに落ちる。部品が場所を選ばなくなる
  • 列からはみ出し、写真も文字も潰れる 同じ部品を、本文にも脇にも記事下にも置ける
  • 親側に container-type: inline-size; を書き、部品側で @container (min-width: 30rem) を見る。
  • 画面全体の骨格を切り替えるときはメディアクエリ。置き場所が変わる部品はコンテナクエリ。

コンテナクエリなら、部品は自分が入っている箱の幅を見ます。部品側から置き場所を知らなくてよくなるので、同じ部品をどこにでも置けます。

このコードで動いている見本です

画面全体の骨格(1カラムか2カラムか)を切り替えるときはメディアクエリ。置き場所が変わりうる部品はコンテナクエリ、と分けます。

間違えやすいところ#

直す例#

架空の案件を1つ例にとります。どこを見て、何をどう直すかを書きます。

歯科医院サイトの「診療時間」カードです。本文の下では横組み、狭いサイドバーでは縦積みにしたい。部品の中に @media (max-width: 48rem) を書いて対応していますが、サイドバーは画面が広いままなので、狭い列に横組みが押し込まれて表が潰れます。

部品が見ているのが画面の幅だからです。親の .side に container-type: inline-size を付け、部品側の分岐を @container (min-width: 30rem) に置き換えると、同じカードが置き場所に合わせて形を変えます。

同じページで、料金の一覧が Flexbox のまま flex-basis: 30% で3列に揃えてありました。項目が4つになった日に崩れます。ここは列を先に決める側なので、Grid の auto-fit と minmax() に替えます。ブレークポイントは1つも書きません。

確認する#

使えるパターン#

この話が要る場面#

このページが答えになる、現場の困り事です。困り事の側から探すと、同じ場所に着きます。

一覧のカードの高さが揃わない

Gridのサブグリッドで、見出し・本文・ボタンの行を列をまたいで揃える。

このコードで動いている見本です

gap と margin のどちらを使うか

並びの中の間隔は gap。端の余白を打ち消す記述が要らなくなる。

このコードで動いている見本です

FlexboxとGridのどちらを使うか

列の幅を揃えたいならGrid、中身の量で幅を変えたいならFlexbox。

このコードで動いている見本です

画面幅で列数を変えたい

repeat(auto-fit, minmax(16rem, 1fr)) だけで折り返る。ブレークポイントを書かなくてよい。

このコードで動いている見本です

部品を置く場所によって形を変えたい

メディアクエリではなくコンテナクエリを使う。画面幅ではなく親の幅で分岐する。

このコードで動いている見本です

文字や余白を画面幅に連動させたい

clamp() を使う。推奨値に rem を含めないと、利用者の文字サイズ設定に追従しなくなる。

このコードで動いている見本です

この場面のほかの困り事と、そのまま貼れる部品は並べる・揃える、余白と幅を決める、CSSで詰まるにまとめてある。逆引きには全188件。

場面で選ぶ#

この値は作業台で決められます。和文の予約ページに載せて、幅と明暗を替えて確かめてから CSS を持ち帰る: 並べ方(Flexbox と Grid)

組みたい場面を選ぶと、Flexbox と Grid のどちらで組むかの判断が1文で出ます。完成 CSS は実物のプレビュー付きです。

Flexbox項目の幅は文字数で決まり、列を揃える必要が無いので Flexbox で組みます。

/* ナビの横並び */
.nav { display: flex; flex-wrap: wrap; align-items: center;
       gap: var(--space-2) var(--space-5); }
.nav a { padding: var(--space-2) var(--space-3); }

この道具は JavaScript で動きます。無効の場合は、上の使い分けの表と下の既定値のコードを使ってください。

出典#

関連#

この資料は、Webサイトを作るときに引くためのものです。 何のために作ったか。作っているのは AK²Lab。