メインコンテンツまでスキップ
  • Created:
  • Updated:
  • Author:
    Takeshi Takatsudo

レスポンシブグリッドパターン

問題

レスポンシブなグリッドレイアウトの作成には、従来、各ブレークポイントで異なる grid-template-columns 値を持つ複数のメディアクエリが必要でした。AIエージェントはほぼ常にカラム数をハードコード(例:grid-template-columns: repeat(3, 1fr))してから、2カラム、1カラムに切り替えるブレークポイントを追加します。これではコンテナ幅が予想外に変わると壊れる脆いレイアウトになります。CSS Grid にはメディアクエリなしでグリッドを本質的にレスポンシブにする組み込み機能があります。

解決方法

repeat()auto-fill または auto-fitminmax() と組み合わせることで、利用可能なスペースに基づいてカラム数を自動調整するグリッドを作成できます。これは RAM パターン(Repeat, Auto, Minmax)と呼ばれることがあります。

auto-fill vs auto-fit

  • auto-fill: コンテナに収まるだけのトラックを作成します。空のトラックはそのまま残りスペースを占有します。
  • auto-fit: コンテナに収まるだけのトラックを作成しますが、空のトラックを幅ゼロに折りたたみ、埋まっているトラックを引き伸ばします。

グリッドのアイテム数がカラム数より少ない場合、違いが顕著になります:

  • auto-fill は空のカラムスロットを保持します(一貫したカラム幅に便利です)。
  • auto-fit は空のスロットを折りたたみ、既存のアイテムを行全体に引き伸ばします。
auto-fill + minmax() グリッド — Mobile / Tablet / Full でリフローを確認

コード例

基本的なレスポンシブグリッド(RAM パターン)

.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1.5rem;
}

この1行で以下のグリッドが作成されます:

  • 各カラムの最小幅は 250px です。
  • カラムは残りのスペースを均等に満たすように伸びます(1fr)。
  • コンテナが縮むと、カラムは自動的に1行あたりの数が減ります。
  • メディアクエリは不要です。

auto-fill: 一貫したカラムスロット

.grid-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
<div class="grid-fill">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<!-- Only 2 items, but empty column slots are preserved -->
</div>

利用可能なスロットよりアイテムが少ない場合でも一貫したカラムサイズにしたいときは auto-fill を使いましょう。

auto-fit: アイテムが引き伸ばされて埋まる

.grid-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
<div class="grid-fit">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<!-- 2 items stretch to fill the entire row -->
</div>

アイテム数に関係なくアイテムが利用可能なスペースを埋めるように伸びてほしいときは auto-fit を使いましょう。

min() によるオーバーフローの防止

minmax(250px, 1fr) でよくある問題は、ビューポートが 250px より狭いとグリッドがオーバーフローすることです。min() を使って修正しましょう:

.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr));
gap: 1.5rem;
}

min(250px, 100%) により、非常に狭い画面でもカラムがコンテナ幅を超えないようになります。

一貫した高さのカードグリッド

.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
gap: 1.5rem;
}

.card {
display: flex;
flex-direction: column;
background: var(--color-surface, #f5f5f5);
border-radius: 0.5rem;
overflow: hidden;
}

.card__body {
flex: 1;
padding: 1.5rem;
}

.card__footer {
padding: 1rem 1.5rem;
margin-block-start: auto;
}

最小カラム数を保証するレスポンシブグリッド

狭い画面でも最低2カラムにしたい場合があります。RAM パターンに最小サイズ用のメディアクエリだけを組み合わせましょう:

.grid-min-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}

@media (min-width: 40rem) {
.grid-min-2 {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
}

非対称レスポンシブレイアウト

一方のカラムを広くしたいレイアウト(例:メインコンテンツ + サイドバー)の場合:

.layout {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
}

@media (min-width: 50rem) {
.layout {
grid-template-columns: 1fr 20rem;
}
}

サイズが異なるアイテムのデンスパッキング

グリッドアイテムのスパンが異なる場合、grid-auto-flow: dense を使ってギャップを埋めましょう:

.masonry-like {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-flow: dense;
gap: 1rem;
}

.masonry-like .wide {
grid-column: span 2;
}

.masonry-like .tall {
grid-row: span 2;
}

Subgrid を使ったコンテンツ揃えのレスポンシブグリッド

カードのコンテンツ(タイトル、テキスト、フッター)を行をまたいで揃える必要がある場合:

.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
gap: 1.5rem;
}

@supports (grid-template-rows: subgrid) {
.card-grid {
grid-template-rows: auto;
}

.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3; /* title, body, footer */
}
}

AIがよくやるミス

  • カラム数をハードコードする: auto-fill/auto-fitminmax() を使う代わりに、grid-template-columns: repeat(3, 1fr) と書いてからメディアクエリで2カラム、1カラムに変更してしまいます。
  • auto-fillauto-fit を混同する: 互換的に使ってしまいます。グリッドのアイテム数がカラム数より少ない場合、挙動が異なります。
  • オーバーフローを防がない: min(250px, 100%) なしで minmax(250px, 1fr) を使い、狭いビューポートで水平オーバーフローを引き起こします。
  • グリッドレイアウトに Flexbox を使う: CSS Grid の auto-fill でより簡潔に解決できるのに、display: flex; flex-wrap: wrap とパーセント幅や gap ハックを使ってしまいます。
  • メディアクエリを多用する: auto-fill/auto-fit に自動処理させる代わりに、カラム数が変わるたびにブレークポイントを追加してしまいます。
  • grid-auto-flow: dense を無視する: アイテムのサイズが異なるときにグリッドにギャップを残してしまい、デンスパッキングを使いません。

使い分け

  • カードグリッド: 商品リスト、ブログ記事グリッド、画像ギャラリーなど、均一なアイテムのグリッドに使いましょう。
  • ダッシュボードレイアウト: 利用可能なスペースを埋めるべきウィジェットやパネルに使いましょう。
  • auto-fill: アイテムが少なくても一貫したカラム幅にしたいとき(例:構造を維持すべき商品グリッド)に使いましょう。
  • auto-fit: アイテムが行を引き伸ばして埋めてほしいとき(例:1〜3個のフィーチャーカードを持つヒーローセクション)に使いましょう。
  • 複雑な非対称レイアウトには不向き: サイドバー、ヘッダー、フッターを持つレイアウトには、明示的な grid-template-columnsgrid-template-areas を使いましょう。

Tailwind CSS

Tailwind はレスポンシブブレークポイントプレフィックス(sm:md:lg:xl:)を使って、異なるビューポート幅でグリッドのカラム数を変更します。ビューポートボタンを使ってグリッドのリフローを確認しましょう。

レスポンシブカードグリッド

Tailwind: レスポンシブグリッド(Mobile / Tablet / Full で確認)

非対称レイアウト

Tailwind: メイン + サイドバーのレスポンシブレイアウト

参考リンク