CSS Gridレイアウト入門|Flexboxと使い分けながら2次元レイアウトをスマートに組む


はじめに

前回の記事ではChrome DevToolsのNetworkパネルを使ってサイトの読み込みパフォーマンスを確認する方法を解説しました。今回はCSS Gridの基本を解説します。「Flexboxは使えるようになったけれどGridはよくわからない」という方が多いのではないでしょうか。GridとFlexboxは競合するものではなく役割が違うものです。2つの違いを理解して使い分けることで、複雑なレイアウトをシンプルなCSSで組めるようになります。


1. GridとFlexboxの使い分け

1.1 一番大切な考え方

シンプルな使い分けの基準:

Flexbox(1次元):
→ 横一列・縦一列に並べるとき
→ アイテムを「行」か「列」の1方向に並べる
→ ナビゲーション・ボタン群・カード横並び

Grid(2次元):
→ 縦と横を同時にコントロールしたいとき
→ 「行」と「列」の両方向を同時に扱う
→ ページ全体のレイアウト・複雑なカードグリッド
→ 「ここだけ2列分の幅にしたい」という場合

1.2 具体例で理解する

Flexboxを使う場面:

✅ ヘッダーのロゴとナビを左右に振り分ける
✅ ボタンの中のアイコンとテキストを横並びにする
✅ フッターのリンク群を横に並べる
✅ カードの中のテキストを縦に積む

Gridを使う場面:

✅ ページ全体を「ヘッダー・サイドバー・メイン・フッター」に分割する
✅ 制作実績を3列グリッドで並べて1つだけ2列分の幅にする
✅ 雑誌風の複雑なレイアウトを組む
✅ 画像ギャラリーで縦横の位置を細かく指定する

💡 「どちらを使うか迷ったらFlexbox」から始めて、Gridが必要な場面を覚えていくのがスムーズです: ほとんどのレイアウトはFlexboxで実装できます。GridはFlexboxでは難しい「2次元の配置」が必要なときに使います。


2. CSS Gridの基本的な書き方

2.1 グリッドコンテナとグリッドアイテム

/*
  グリッドコンテナ(親要素):
  display: grid を指定した要素

  グリッドアイテム(子要素):
  グリッドコンテナの直接の子要素
*/

/* グリッドコンテナの設定 */
.grid-container {
    display: grid;
}

/* 子要素は自動的にグリッドアイテムになる */
.grid-item {
    /* グリッドアイテムとしての設定 */
}

2.2 列の定義:grid-template-columns

/* 3列の均等グリッドを作る */
.grid-3col {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    /* 省略形:repeat(3, 1fr) */
}

/*
  「fr」とは?
  → Fraction(分数)の略
  → 利用可能なスペースを分割する単位
  → 1fr 1fr 1fr → 残りスペースを3等分
  → 2fr 1fr → 残りスペースを2:1で分割
*/

/* よく使うパターン */
.layout-sidebar {
    display: grid;
    grid-template-columns: 240px 1fr;
    /* 左240px固定・右は残り全部 */
}

.layout-main-sub {
    display: grid;
    grid-template-columns: 2fr 1fr;
    /* 左2/3・右1/3 */
}

.layout-3col {
    display: grid;
    grid-template-columns: repeat( 3, 1fr );
    /* 3列均等 */
}

.layout-4col {
    display: grid;
    grid-template-columns: repeat( 4, 1fr );
    /* 4列均等 */
}

2.3 行の定義:grid-template-rows

/* 行も同様に定義できる */
.grid-rows {
    display:               grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows:    200px 1fr 100px;
    /*
      1行目:高さ200px
      2行目:残りの高さをすべて使う
      3行目:高さ100px
    */
}

2.4 ガター(溝):gap

/* gap でアイテム間の余白を設定する */
.grid-with-gap {
    display:               grid;
    grid-template-columns: repeat( 3, 1fr );
    gap:                   24px;
    /* 全方向に24pxの溝 */
}

/* 縦横で別々に設定する場合 */
.grid-gap-separate {
    display:               grid;
    grid-template-columns: repeat( 3, 1fr );
    row-gap:               32px;    /* 行間 */
    column-gap:            16px;    /* 列間 */
    /* または gap: 32px 16px; (行 列の順) */
}

3. repeat()とauto-fill・auto-fitで柔軟に

3.1 repeat()関数

/* repeat(繰り返し回数, サイズ) */

/* 3列均等 */
grid-template-columns: repeat( 3, 1fr );

/* 4列 左から200px 1fr 1fr 200px */
grid-template-columns: 200px repeat( 2, 1fr ) 200px;

/* 12列グリッド(Bootstrap風) */
grid-template-columns: repeat( 12, 1fr );

3.2 auto-fillとauto-fit

/* auto-fill:
   可能な限り多くの列を自動で作る
   最小幅を下回る場合は空の列を残す */

.card-grid-auto {
    display:               grid;
    grid-template-columns: repeat( auto-fill, minmax( 280px, 1fr ) );
    gap:                   24px;
}

/*
  minmax(280px, 1fr) の意味:
  → 最小280px・最大1fr(残りスペース)
  → 280px未満にはならない
  → 280px以上は均等に広がる

  → 画面幅が900px の場合:
    3列(280×3=840px)が収まる
    → 自動で3列になる

  → 画面幅が600px の場合:
    2列(280×2=560px)が収まる
    → 自動で2列になる

  メディアクエリなしでレスポンシブになる!
*/

/* auto-fit:
   空の列を縮めて残りのアイテムで埋める */
.card-grid-fit {
    display:               grid;
    grid-template-columns: repeat( auto-fit, minmax( 280px, 1fr ) );
    gap:                   24px;
}

💡 repeat(auto-fill, minmax(280px, 1fr))はレスポンシブ対応の最強パターンです: メディアクエリを一切書かずに、画面幅に応じて自動的に列数が変わるグリッドができます。カードグリッドを実装するときにまず試してほしいコードです。


4. グリッドアイテムの配置を制御する

4.1 grid-column・grid-rowで位置を指定する

/*
  グリッドラインの番号:
  3列グリッドの場合

  |  1  |  2  |  3  |
  1     2     3     4  ← ラインの番号

  grid-column: 開始ライン / 終了ライン
*/

/* 2列分の幅を占める */
.item-wide {
    grid-column: 1 / 3;
    /* ライン1からライン3まで → 2列分 */
}

/* 最初から最後まで(全幅) */
.item-full {
    grid-column: 1 / -1;
    /* -1 = 最後のラインを意味する */
}

/* 2列分の幅(spanを使う方法) */
.item-span2 {
    grid-column: span 2;
    /* 現在位置から2列分占める */
}

/* 2行分の高さを占める */
.item-tall {
    grid-row: span 2;
    /* 現在位置から2行分占める */
}

4.2 実践例:雑誌風レイアウト

/* 6列グリッドで雑誌風レイアウト */
.magazine-grid {
    display:               grid;
    grid-template-columns: repeat( 6, 1fr );
    grid-template-rows:    auto;
    gap:                   16px;
}

/* メイン記事(左4列・2行分) */
.article-main {
    grid-column: 1 / 5;  /* 4列分 */
    grid-row:    1 / 3;  /* 2行分 */
}

/* サイド記事1(右2列・1行目) */
.article-side1 {
    grid-column: 5 / 7;  /* 2列分 */
    grid-row:    1 / 2;  /* 1行目 */
}

/* サイド記事2(右2列・2行目) */
.article-side2 {
    grid-column: 5 / 7;  /* 2列分 */
    grid-row:    2 / 3;  /* 2行目 */
}

/* 下段:3等分 */
.article-bottom {
    grid-column: span 2;  /* 2列分ずつ(3つで6列) */
}

5. grid-template-areasで直感的に配置する

5.1 grid-template-areasとは

/*
  grid-template-areas:
  グリッドの各エリアに名前を付けて
  視覚的にレイアウトを定義できる機能

  コードを見るだけでレイアウトがイメージできる
*/

/* ページ全体のレイアウト */
.page-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    grid-template-rows:    60px 1fr 60px;
    grid-template-areas:
        "header  header"
        "sidebar main"
        "footer  footer";
    min-height: 100vh;
}

/* 各エリアに名前を割り当てる */
.header {
    grid-area: header;
}

.sidebar {
    grid-area: sidebar;
}

.main {
    grid-area: main;
}

.footer {
    grid-area: footer;
}

5.2 レスポンシブ対応との組み合わせ

/* スマートフォン:1カラム */
.page-layout {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows:    auto;
    grid-template-areas:
        "header"
        "main"
        "sidebar"
        "footer";
}

/* PC:サイドバー付き2カラム */
@media ( min-width: 1024px ) {
    .page-layout {
        grid-template-columns: 240px 1fr;
        grid-template-rows:    60px 1fr 60px;
        grid-template-areas:
            "header  header"
            "sidebar main"
            "footer  footer";
    }
}

6. よく使うGridレイアウトパターン集

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

/* 最も使用頻度の高いパターン */
.card-grid {
    display:               grid;
    grid-template-columns: repeat( auto-fill, minmax( 280px, 1fr ) );
    gap:                   24px;
}

/* メディアクエリで厳密に制御したい場合 */
.card-grid-strict {
    display: grid;
    gap:     24px;

    /* スマホ:1列 */
    grid-template-columns: 1fr;
}

@media ( min-width: 640px ) {
    .card-grid-strict {
        grid-template-columns: repeat( 2, 1fr );
    }
}

@media ( min-width: 1024px ) {
    .card-grid-strict {
        grid-template-columns: repeat( 3, 1fr );
    }
}

6.2 Holy Grail レイアウト

/* 定番の3カラムレイアウト
   ヘッダー・左サイド・メイン・右サイド・フッター */
.holy-grail {
    display:               grid;
    grid-template-columns: 200px 1fr 200px;
    grid-template-rows:    auto 1fr auto;
    grid-template-areas:
        "header  header  header"
        "sidebar main    aside"
        "footer  footer  footer";
    min-height:            100vh;
}

/* スマホでは1カラム */
@media ( max-width: 767px ) {
    .holy-grail {
        grid-template-columns: 1fr;
        grid-template-areas:
            "header"
            "main"
            "sidebar"
            "aside"
            "footer";
    }
}

6.3 画像ギャラリー(Pinterest風)

/* Masonry(段違い)風レイアウト */
.gallery-grid {
    display:               grid;
    grid-template-columns: repeat( 3, 1fr );
    grid-template-rows:    masonry; /* 実験的機能 */
    gap:                   16px;
}

/* 現時点で安定して使えるアプローチ */
.gallery-grid-stable {
    display:               grid;
    grid-template-columns: repeat( 3, 1fr );
    gap:                   16px;
}

/* 特定の画像を大きく表示する */
.gallery-item-featured {
    grid-column: span 2;
    grid-row:    span 2;
}

6.4 フォームレイアウト

/* 問い合わせフォームの2カラムレイアウト */
.form-grid {
    display:               grid;
    grid-template-columns: 1fr 1fr;
    gap:                   16px;
}

/* 名前フィールドは左半分 */
.form-field-name {
    grid-column: 1 / 2;
}

/* メールフィールドは右半分 */
.form-field-email {
    grid-column: 2 / 3;
}

/* 本文・送信ボタンは全幅 */
.form-field-message,
.form-submit {
    grid-column: 1 / -1;
}

/* スマホでは1カラム */
@media ( max-width: 640px ) {
    .form-grid {
        grid-template-columns: 1fr;
    }

    .form-field-name,
    .form-field-email {
        grid-column: 1 / -1;
    }
}

7. GridとFlexboxを組み合わせる

7.1 外側Grid・内側Flexboxのパターン

/* ページ全体はGridで大枠を作る */
.page {
    display:               grid;
    grid-template-columns: 1fr;
    grid-template-rows:    auto 1fr auto;
    min-height:            100vh;
}

/* ヘッダーの中はFlexboxで横並び */
.header {
    display:         flex;
    align-items:     center;
    justify-content: space-between;
    padding:         0 40px;
    height:          80px;
}

/* カードグリッドはGridで列を管理 */
.card-grid {
    display:               grid;
    grid-template-columns: repeat( 3, 1fr );
    gap:                   24px;
}

/* カードの中はFlexboxで縦積み */
.card {
    display:        flex;
    flex-direction: column;
}

/* カードのフッター(タグなど)を下部に固定 */
.card-footer {
    margin-top: auto; /* 上の余白を自動で埋めて下に寄せる */
}

💡 Grid for layout・Flex for components という原則で考えるとシンプルです: ページ全体の骨格はGrid・各UIコンポーネント内部の並びはFlexboxという分担が多くのケースで自然に当てはまります。


8. デバッグ:GridをDevToolsで確認する

8.1 Chrome DevToolsでGridを可視化する

GridのデバッグはDevToolsが便利:

① DevToolsを開く(F12)

② 「Elements」タブでグリッドコンテナの要素を探す

③ 要素の横に「grid」と表示されたバッジをクリックする

④ キャンバス上にグリッドラインが表示される:
   → 列ライン(縦の線)に番号が表示される
   → 行ライン(横の線)に番号が表示される
   → ガター(gap)も色付きで表示される

⑤「Layout」タブでGridの設定を確認できる:
   → 「Grid overlays」でどのグリッドを表示するか選べる
   → ラインナンバー・エリア名を表示できる

→ grid-template-areas を使っているときは
  各エリアの名前が表示されてわかりやすい

9. よくある間違いと対処法

9.1 子要素が意図した位置に配置されない

/* ❌ よくある間違い:
   グリッドアイテムに display:flex を使うと
   Gridの配置が効かなくなることがある */

.grid-container {
    display:               grid;
    grid-template-columns: 1fr 1fr;
}

/* ❌ これはOK(アイテムにflexを使うのはOK) */
.grid-item {
    display:        flex;  /* アイテム内部の配置はOK */
    flex-direction: column;
}

/* ✅ 正しい理解:
   grid-column や grid-row は
   グリッドコンテナの直接の子要素にしか効かない
   孫要素には効かない */

9.2 gapが効かない

/* ❌ 古いCSSではgapが使えない場合がある */
.grid {
    display: grid;
    grid-gap: 24px; /* 古い書き方 */
}

/* ✅ 現代のCSSではgapを使う */
.grid {
    display: grid;
    gap: 24px; /* 新しい書き方・Flexboxでも使える */
}

9.3 grid-template-areasの書き方ミス

/* ❌ NG:エリア名に特殊文字・スペースは使えない */
.grid {
    grid-template-areas:
        "header-top header-top"  /* ハイフンはNG */
        "side bar main";         /* スペースはNG(別の名前として解釈される) */
}

/* ✅ OK:英数字とアンダースコアのみ */
.grid {
    grid-template-areas:
        "header header"
        "sidebar main";
}

/* ✅ 空のセルは「.」で表す */
.grid {
    grid-template-areas:
        "header header header"
        ".      main   aside"  /* 左セルを空にする */
        "footer footer footer";
}

10. 実践チェックリスト

✓ display: grid と grid-template-columns でグリッドコンテナを定義できたか

✓ repeat(3, 1fr) で3列均等グリッドを作れたか

✓ gap でアイテム間の余白を設定できたか

✓ repeat(auto-fill, minmax(280px, 1fr)) でレスポンシブなカードグリッドを作れたか

✓ grid-column: span 2 で特定のアイテムを2列分に広げられたか

✓ grid-template-areas でエリアに名前を付けてレイアウトを定義できたか

✓ Chrome DevToolsでグリッドラインを可視化して意図通りに配置されているか確認したか

✓ スマートフォン表示でも崩れていないかメディアクエリと組み合わせて確認したか


まとめ

今回はCSS Gridの基本とFlexboxとの使い分けを解説しました。ポイントをまとめると:

  • FlexboxはナビやボタンなどUI部品の1次元の並びに・GridはページレイアウトやカードグリッドなどI2次元の配置に使う
  • grid-template-columns: repeat(3, 1fr) で3列均等グリッドを作れる・fr は利用可能なスペースを分割する単位
  • repeat(auto-fill, minmax(280px, 1fr)) はメディアクエリなしで自動的に列数が変わるレスポンシブグリッドの最強パターン
  • grid-column: span 2 で特定のアイテムを複数列にまたがって配置できる・1 / -1 で全幅になる
  • grid-template-areas でエリアに名前を付けると視覚的にレイアウトを定義でき可読性が高くなる
  • 外側はGridで骨格を作り・内側のUIコンポーネントはFlexboxで並べる組み合わせが実践での定番
  • Chrome DevToolsのElementsパネルでgridバッジをクリックするとグリッドラインを可視化できる

次の記事では、JavaScriptのイベントハンドリングの基本を解説します。クリック・スクロール・フォーム送信などのイベントを正しく扱う方法をお届けします。お楽しみに!

コメント

タイトルとURLをコピーしました