Last updated on

CSS Grid:minmax と auto-fit / auto-fill の整理

  • CSS
  • Grid
  • レイアウト

前提

grid-template-columns: repeat(3, 1fr); のように 列数を数字で決めて repeat だけ使う分には慣れていた。一方で minmax()auto-fit / auto-fill はほとんど手を付けず、必要になったときに真似書きで済ませることが多かった。

minmaxauto-fit / auto-fill について、基本的な使い方と共通点・差を整理して、今後は活用できるようにしたい。

検証用デモページで実際の挙動を確認しながら整理した。
grid-template-columns

minmax

minmax(最小, 最大) は、列トラックの幅を下限と上限のあいだに収めたいときに使う。grid-template-columns の列定義の一部として repeat() と組み合わせるのが一般的である。

基本的な使い方

最小値と最大値を指定する。
例: grid-template-columns: repeat(3, minmax(100px, 300px));

活用例:改行させずに幅を守り、横スクロールへ回す

「中身のテキストを 無理に折り返したくない」「列として ある程度の最小幅は保ちたい」といったとき、各列に minmax(◯px, …)最小側を効かせると、狭い画面ではトラックの合計幅がコンテナを超えやすくなる。コンテナに overflow-x: auto を付ければ、横スクロールで閲覧させるレイアウトにできる。

検証デモ では repeat(3, minmax(340px, 350px))overflow-x: auto の組み合わせが載っている(数値は例として読み替えてよい)。画面幅を狭めると、スクロールバーが出てくる。

auto-fit / auto-fill との組み合わせ

repeat(auto-fit, minmax(◯px, 1fr)) のように minmax の第 2 引数に 1fr を置くと、余った幅の配分のされ方が、後述の auto-fit と auto-fill のどちらかで大きく変わる。minmax 側で「最小幅はここまで」という 下限を決めておくイメージで読むと、auto-* の節とつながりやすい。

auto-fit と auto-fill

repeat(5, 1fr) のように 列数を固定できない(またはブレークポイントのたびに数字を書き換えたくない)とき、コンテナ幅と「1 列の最小幅」から列数を自動で決めるのが repeat の第一引数にある auto-fillauto-fit である。

実際の見た目の対比は、デモの auto-fitauto-fill を並べて触ると理解が進みやすい。

共通の振る舞い(ざっくり)

どちらも、コンテナに 載せられるだけの列トラックを(minmax の最小値などを手がかりに)用意しようとする方向は同じである。細部は仕様書の定義に委ねるが、日々の実装では 「空いた列をどう扱うか」 の差が結果に出る。

差が出る振る舞い(空トラックと 1fr

ざっくり言うと、次のような整理になる(minmax(◯px, 1fr) を想定)。

  • auto-fill: 親コンテナに まだ余白があるとき、中身のない列(空のグリッドトラック)も作られる側に振る舞う。1fr で余白を配分するとき、その 空の列にも幅の伸びが割り当てられる。その結果、アイテムが載っている列だけが親いっぱいに広がるわけではなく、トラック 1 本分あたりの伸びにとどまることが多い。
  • auto-fit: 同様に余白があっても、アイテムがない繰り返し列は折りたたまれる(空トラックは幅 0 に近い扱いになる)。1fr の余白は 実質アイテムのある列に回りやすく親要素の幅いっぱいまで広がることがある。アイテムが 1 つだけのときなど、1 カードが横に大きく見える状況になりうる。

開発者ツールのグリッドオーバーレイで見ると、空トラックが残るかどうかの差が分かりやすい。下図は アイテムが 1 つだけのときの対比である(上段 auto-fit、下段 auto-fill)。

DevTools で可視化した auto-fit と auto-fill の対比(グリッドアイテムが 1 つのとき)

件数が少ないレイアウトでは どちらを選ぶかでカード幅の印象が変わるため、デザインの意図に合わせて切り替える判断になる。

固定の列数が必要な場面

repeat(3, 1fr) のように 列数を数字で書く場合、画面が狭くなって列を減らしたいときは ブレイクポイントごとに repeat(2, 1fr) へ切り替える、といった 明示的な指定が必要になる。反面、どの幅で何列かがコード上はっきりする。

一方、auto-fitauto-fill を使うと コンテナ幅に応じて列数が勝手に決まるため、幅の断ち切りごとに列数だけ書き換える手間はかからない。可変グリッドとしてはとても便利である。

ただし 列数が fluid に変わること自体が、レイアウトの意図を壊すことがある。次のようなときは repeat(N, 1fr) で列数をはっきり決めた方がデザインと折り合いが付きやすい。

例: 動的サイトの一覧で 投稿を最大 9 件だけ並べる。3 列なら 3×3 でちょうど埋まり、行のバランスが取れる。ところが auto-fit / auto-fill 任せで幅によって 2 列になってしまうと、最終行に 1 件だけ残り、余白や視線の止まり方が意図とズレやすい。この場合は 列数をメディアクエリで明示する(狭い画面では 2 列にするが、9 件前提なら 3 列に固定し続ける幅帯を広く取る件数や可視件数を調整する、など)方が筋がよい。

要するに 「常にきれいな行列になる件数・列の関係」がデザインの条件になっているときは、自動列数に頼りすぎない。

グリッドアイテムの直下の子に min-width: 0 を付けると、長いテキストなどが原因で 列幅だけ意図せず膨らむのを防ぎやすい。検証デモの .p-grid でも同様の指定が入っている。

参考