CSS Gridの前は、適切なページレイアウトを構築するにはフロート、クリアフィックス、ネガティブマージン、そして列が崩れないようにという祈りが必要でした。Flexboxは助けになりましたが、本質的に1次元です — 行または列が得られますが、両方ではありません。CSS Gridは、実際に2次元レイアウト用に設計されたCSSネイティブの最初のレイアウトシステムです。課題はブラウザサポートではありません — 2017年から普遍的です。課題はAPIの表面積が大きく、基礎となるモデルが明確でないと混乱するほど命名が一貫していないことです。この記事は実際の作業で使用する部分に焦点を当てています。

行、列、グリッドコンテナ

すべてはコンテナのdisplay: gridから始まります。設定されると、直接の子は自動的にグリッドアイテムになります — クラスは不要です。列と行のトラックはgrid-template-columnsgrid-template-rowsで定義します。

最初に理解すべき重要な単位はfr — 分数単位です。固定サイズのトラックが考慮された後のグリッドコンテナの利用可能スペースの分数を表します。1frは「残りのスペースの1つのシェアを取る」を意味します。1fr 1frの2列は等しい半分を意味します。2fr 1frは最初の列が2番目の列の2倍を取得することを意味します。これがフルードグリッドを自然に感じさせる単位です。

css
/* 3-column blog card layout */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
  gap: 1.5rem;
}

/* repeat(3, 1fr) is shorthand for: 1fr 1fr 1fr */
/* auto rows size to their content */

repeat(n, track)は同じトラックサイズを5回書かなくて済むショートカットです。混合値でも機能します:repeat(3, 1fr 2fr)は狭いトラックと広いトラックが交互になる6列グリッドを作ります。行については、autoがほぼ常に望ましい選択です — 明示的に固定高さが必要でない限り、行はコンテンツに合わせてサイズ調整されます。

html
<div class="card-grid">
  <article class="card">
    <img src="/posts/grid-post-1.jpg" alt="CSS Grid post 1">
    <h2>Getting Started with Grid</h2>
    <p>A practical intro for developers moving from Flexbox.</p>
  </article>
  <article class="card">
    <img src="/posts/grid-post-2.jpg" alt="CSS Grid post 2">
    <h2>Grid vs Flexbox</h2>
    <p>Which layout tool to reach for, and when.</p>
  </article>
  <article class="card">
    <img src="/posts/grid-post-3.jpg" alt="CSS Grid post 3">
    <h2>Responsive Grids Without Media Queries</h2>
    <p>Using minmax() to handle reflow automatically.</p>
  </article>
</div>

gapプロパティ

Grid以前は、レイアウトの子要素間にスペースを追加するにはマージンが必要でした — そしてマージンは最後の子をリセットすること、崩れに対処すること、補正のためにコンテナにネガティブマージンを追加することを意味しました。gapはこれをきれいに解決します。スペースはトラック間にのみ追加され、グリッドの外側の端には追加されません。

css
/* Uniform gap between all rows and columns */
.card-grid {
  gap: 1.5rem;
}

/* Different row and column gaps */
.dashboard {
  row-gap: 2rem;
  column-gap: 1rem;
}

/* gap is shorthand: row-gap then column-gap */
.dashboard {
  gap: 2rem 1rem;
}
注:gapはFlexboxでも機能します(古いgrid-gapエイリアスを置き換えました)。コンポーネントにすでにFlexboxを使用していてアイテム間のスペースだけが必要な場合、Gridに切り替えなくてもそこでgapを使用できます。

アイテムの明示的な配置

デフォルトでは、グリッドアイテムはソース順序で次に利用可能なセルに流れます。しかし、Gridの本当の力はアイテムをどこにでも配置できること — さらに複数のトラックにまたがることもできることです。プロパティはgrid-columngrid-rowで、グリッドライン(トラック間の線、1から番号付け)を参照します。

css
/* Dashboard where the first card spans 2 columns */
.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.card--featured {
  grid-column: 1 / 3;   /* start at line 1, end at line 3 */
}

/* span keyword: simpler when you don't care about exact position */
.card--featured {
  grid-column: span 2;  /* occupy 2 column tracks from wherever it lands */
}

/* Spanning rows too */
.card--tall {
  grid-row: span 2;     /* occupy 2 row tracks */
}

/* Explicit positioning: place a panel in column 3-5, row 1-2 */
.sidebar {
  grid-column: 3 / 5;
  grid-row: 1 / 2;
}

行番号は左/上端から1で始まり、nがトラック数の場合n+1まで続きます。負の行番号は右/下から数えます:grid-column: 1 / -1は列数に関係なくグリッドの全幅にアイテムを伸ばします — 複数列コンテナ内の全幅要素に便利なトリックです。

grid-template-areas — レイアウトに名前を付ける

これがGridをページレベルのレイアウトに真に優れたものにする機能であり、CSS全体で最も読みやすいAPIです。ライン番号でアイテムを配置する代わりに、CSSでASCIIアートとしてレイアウトを描き、次に各アイテムが占める名前付きエリアを指定します。grid-template-areas仕様では、すべての行が同じ数のセルを持つ必要があり、各名前付きエリアは長方形でなければなりません — L字形は不可です。

css
/* Full page layout: header, sidebar, main, footer */
.page-shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
  gap: 0;
}

.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }
html
<div class="page-shell">
  <header class="page-header">Site header / nav</header>
  <nav class="page-sidebar">Sidebar navigation</nav>
  <main class="page-main">Primary content</main>
  <footer class="page-footer">Footer</footer>
</div>

テンプレート文字列のピリオド(.)はセルを意図的に空にします。複数のセルに同じ名前を重ねてそれらをまたがらせることもできます — それが上記の"header header"が行っていることです。異なるビューポイントのためにレイアウトをリサイズまたは再構成する場合、複数のgrid-column宣言を探し回る代わりに、1か所でテンプレート文字列を更新します。

auto-fillとauto-fitとminmax()

メディアクエリなしのレスポンシブグリッドの背後にあるパターンは、Gridの最も実用的なトリックの1つです:repeat(auto-fill, minmax(250px, 1fr))。分解すると — minmax(250px, 1fr)は各列が少なくとも250px幅で、利用可能なスペースを埋めるように拡張できることを示します。auto-fillはその制約でコンテナに収まる限り多くの列を作成するようGridに指示します。結果は、ビューポートが変わると自動的に列を取得および失うグリッドです。

css
/* Product card grid — reflows automatically, no media queries */
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1.5rem;
}

/* auto-fit collapses empty tracks — items stretch to fill the container */
.product-grid--stretch {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.5rem;
}

auto-fillauto-fitの違いは、列よりアイテムが少ない場合に微妙ですが重要です。auto-fillでは、空の場合でもGridは潜在的なトラックのためにスペースを確保します — アイテムは最小幅のままです。auto-fitでは、空のトラックはゼロに折り畳まれ、アイテムは行を埋めるために展開します。アイテムに利用可能なスペースを使用させたい製品グリッドやギャラリーでは、auto-fitの方が通常見栄えが良いです。コンテナを満たすことよりも一定のアイテム幅が重要なグリッドには、auto-fillが正しい選択です。

ブラウザサポートの注:minmax()を使ったauto-fillauto-fitは優れたサポートがあります — caniuseによると97%+のグローバル対応。今日のあらゆる現代的なプロジェクトでフォールバックなしにこのパターンを使用できます。

Gridでの整列

GridはFlexboxと同じボックス整列モジュールを使用しているため、Flexboxを既に知っていればプロパティ名は直接対応します。主要なメンタルモデル:justifyはインライン軸(ほとんどの書き込みモードで水平)で動作し、alignはブロック軸(垂直)で動作します。

  • justify-items / align-items — グリッドセル内のすべてのアイテムのデフォルト整列。デフォルトはstretchで、グリッドアイテムが自動的にセルを埋める理由です。
  • justify-content / align-content — グリッドがコンテナより小さい場合、コンテナ内のトラック自体を配布します(フレックスコンテナのjustify-contentに類似)。
  • justify-self / align-self — 単一アイテムの整列を上書きします。他のアイテムが伸びている間に1つのアイテムを中央に配置したい場合に便利です。
  • 値:startendcenterstretchspace-betweenspace-aroundspace-evenly(最後の3つは*-contentのみ)。
css
/* Center all card content within its cell */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: start;     /* cards align to their cell top, not stretched */
  gap: 1.5rem;
}

/* Center a single call-to-action card both ways */
.card--cta {
  justify-self: center;
  align-self: center;
}

/* Distribute tracks with space between — useful for nav bars */
.nav-grid {
  display: grid;
  grid-template-columns: auto auto auto;
  justify-content: space-between;
}

Flexboxから来た場合、主な違いはGridの整列が2次元空間で動作することです — 両方の軸を同時に制御できます。Flexboxでは、交差軸の整列はアイテムの行または列全体に適用されます;Gridでは、各アイテムに独自のセルがあるため、justify-selfalign-selfはラッパー要素なしにアイテムごとの制御を提供します。

実際のレイアウト:完全なダッシュボードシェル

ダッシュボードアプリケーション用の完全なCSS Gridページ構造を紹介します — ヘッダー、折り畳み可能なナビゲーションサイドバー、独自の内部グリッドを持つメインコンテンツエリア、フッター。これはSaaSダッシュボードや管理パネルの最外層レイアウトシェルとして使用するパターンです。

css
/* ── Dashboard shell ──────────────────────────────────── */
.dashboard-shell {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 56px 1fr 44px;
  grid-template-areas:
    "topbar  topbar"
    "sidenav content"
    "sidenav footer";
  min-height: 100vh;
}

.dashboard-topbar  { grid-area: topbar;  background: #1e293b; }
.dashboard-sidenav { grid-area: sidenav; background: #0f172a; overflow-y: auto; }
.dashboard-content { grid-area: content; padding: 1.5rem; overflow-y: auto; }
.dashboard-footer  { grid-area: footer;  background: #f8fafc; border-top: 1px solid #e2e8f0; }

/* ── Collapsed sidebar variant ────────────────────────── */
.dashboard-shell--collapsed {
  grid-template-columns: 56px 1fr;
}

/* ── Content area — internal card grid ─────────────────── */
.dashboard-content {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  grid-template-rows: auto;
  align-content: start;
  gap: 1.25rem;
}

/* Stat cards take one column each; the main chart spans all */
.stat-card  { /* auto-placed, one column */ }
.main-chart { grid-column: 1 / -1; }   /* always full width */

/* ── Responsive: collapse to single-column on small screens */
@media (max-width: 768px) {
  .dashboard-shell {
    grid-template-columns: 1fr;
    grid-template-rows: 56px 1fr auto 44px;
    grid-template-areas:
      "topbar"
      "content"
      "sidenav"
      "footer";
  }
}
html
<div class="dashboard-shell">
  <header class="dashboard-topbar">
    <a href="/dashboard" class="brand">AppName</a>
    <nav class="topbar-actions">
      <button class="btn-icon" aria-label="Notifications">
        <span class="icon-bell"></span>
      </button>
      <img src="/avatar/user.png" class="user-avatar" alt="User menu">
    </nav>
  </header>

  <nav class="dashboard-sidenav">
    <ul>
      <li><a href="/dashboard">Overview</a></li>
      <li><a href="/dashboard/analytics">Analytics</a></li>
      <li><a href="/dashboard/users">Users</a></li>
      <li><a href="/dashboard/settings">Settings</a></li>
    </ul>
  </nav>

  <main class="dashboard-content">
    <div class="stat-card">Monthly Revenue</div>
    <div class="stat-card">Active Users</div>
    <div class="stat-card">Churn Rate</div>
    <div class="main-chart">Revenue Chart (full width)</div>
  </main>

  <footer class="dashboard-footer">
    <p>AppName v2.4.1 &mdash; <a href="/status">System Status</a></p>
  </footer>
</div>

この例で注目すべき点がいくつかあります。フッターはテンプレートエリア定義を使用して大きな画面ではsidenav列に配置され、メインコンテンツのスクロールエリアから視覚的に分離されています。行の1frとコンテンツペインのoverflow-y: autoは、コンテンツエリアが独立してスクロールすることを意味します — トップバーとサイドナブは固定されたまま、これが標準的なダッシュボードのUXです。下部の@mediaクエリはHTMLに一切触れずにモバイル用のグリッドエリアを並べ替えます。

まとめ

CSS Gridの学習曲線は主に命名から来ています — ライン、トラック、エリア、fr単位 — しかしモデルが分かれば、驚くほど直接的です。実際のレイアウトには:ページシェルにはgrid-template-areasを使用(ワイヤーフレームのように読めます)、レスポンシブカードグリッドにはrepeat(auto-fit, minmax())を使用、標準的なフローを破るアイテムには明示的なgrid-column: span Nを使用します。実際の作業の90%ではGridのAPI全体は必要ありません — これらのパターンがほとんどをカバーします。

さらに読むには:CSS-TricksのGrid完全ガイドは最良の単一ページリファレンスです;MDNのCSS Gridドキュメントはすべてのプロパティを深く掘り下げます;W3C CSS Grid Level 1仕様はエッジケースの正確な動作を理解したい場合に驚くほど読みやすいです。ブラウザの互換性は優れています — caniuse.com/css-gridで現在の数値を確認してください。ライブプロジェクトで作業しておりCSSを整理したい場合、このサイトのCSSフォーマッターがスタイルシートを整形・美化します。