Featured image of post CSS Gridのsubgridを使ってカードデザインの整列を完璧にする Featured image of post CSS Gridのsubgridを使ってカードデザインの整列を完璧にする

CSS Gridのsubgridを使ってカードデザインの整列を完璧にする

CSS Gridのsubgridプロパティを使い、ネストされた子グリッド要素を親グリッドのトラックラインに正確に整列させる手法を解説。カードレイアウトでの高さ揃えや複雑なグリッドデザインを実現する実践的な使い方とレイアウト設計のコツを詳しく紹介します。

はじめに

Webサイトのレイアウトで頻出する「カード型レイアウト(Card Layout)」において、開発者を悩ませてきた長年の問題があります。

それは、**「カード内の各パーツ(画像、タイトル、説明文、フッターボタン)の高さを、隣り合う他のカードと完璧に整列させたい」**というケースです。

これまでの CSS Grid や Flexbox では、カード全体の高さを揃えることは簡単でしたが、カード内部のタイトルの長さや説明文の文字数が異なると、パーツごとの位置がズレてしまいがちでした。

この課題を解決するために追加された機能が、CSS Grid の subgrid 値です。本記事では、subgrid の基本的な使い方と、それを用いた美しいカード整列レイアウトのテクニックを解説します。


1. 従来のネストしたグリッドの問題点

subgrid がない場合、隣接するカード同士で内部要素の高さを揃えようとすると、どのような限界があったかを見てみましょう。

HTML構造

<div class="grid-container">
  <div class="card">
    <h3 class="card-title">短いタイトル</h3>
    <p class="card-desc">短い説明文です。</p>
    <button class="card-btn">詳細</button>
  </div>
  <div class="card">
    <h3 class="card-title">非常に長くて複数行に折り返されるタイトル</h3>
    <p class="card-desc">こちらは長い説明文です。複数行にわたってテキストが表示されます。</p>
    <button class="card-btn">詳細</button>
  </div>
</div>

従来のCSSでのアプローチ

.grid-container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

.card {
  display: flex;
  flex-direction: column;
  justify-content: space-between; /* パーツを上下に分散配置する */
}
  • 課題: この設定では、カード全体の高さは揃いますし、ボタンは最下部に配置されます。しかし、「タイトルの下端」や「説明文の開始位置」は、隣り合うカードと揃いません。 タイトルが2行のカードと1行のカードが並ぶと、説明文の位置がズレてしまい、デザインに統一感がなくなります。

2. subgridの仕組みと解決策

subgrid を使用すると、ネストされた子要素(カード内部)が、「親要素(コンテナ)が定義しているグリッド定義」をそのまま引き継いで共有することができます。

これにより、すべてのカードのタイトルが一律で親の「タイトル行(Row)」を共有し、説明文も親の「説明文行」を共有するため、完璧な整列が実現します。

改善されたCSS

/* 1. 親コンテナで、カード内の行の高さもあらかじめ定義しておく */
.grid-container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

/* 2. カード自体を縦方向のグリッドとして定義し、3行分の高さを親と共有させる */
.card {
  display: grid;
  /* 親のグリッドから行の定義を引き継ぐ(これがsubgrid) */
  grid-template-rows: subgrid;
  /* カードは親グリッドの縦方向で「3行分」を占有することを明示する */
  grid-row: span 3;
  
  gap: 10px;
  background: #f9f9f9;
  padding: 15px;
  border-radius: 8px;
}

/* 3. カード内の要素は自動的にsubgridの各行に割り当てられる */
.card-title {
  grid-row: 1; /* 1行目 */
}
.card-desc {
  grid-row: 2; /* 2行目 */
}
.card-btn {
  grid-row: 3; /* 3行目 */
}

なぜこれで揃うのか?

この設定では、grid-template-rows: subgrid を指定したことで、すべての .card が同じグリッドトラック(親コンテナが暗黙的または明示的に作る行)を共有します。

隣り合うカードのうち「最も長いタイトル」の高さに合わせて、すべてのカードの grid-row: 1(タイトル行)の高さが自動的に伸長し、結果として説明文の開始位置が完璧に揃います。


3. 列方向(Columns)での活用例

subgrid は行(縦方向)だけでなく、列(横方向)に対しても適用できます。

例えば、フォーム画面において、「ラベル」と「入力フィールド」が並んだコンポーネントが縦に積み重なっている場合、各コンポーネントの中でラベルの文字長さが異なっていても、横幅のグリッドラインを完全に揃えることができます。

.form-row {
  display: grid;
  grid-template-columns: subgrid; /* 親のラベル幅・フィールド幅の比率を引き継ぐ */
  grid-column: span 2;
}

これにより、各行のフォームパーツが左右に綺麗に整列し、見栄えの良いフォームレイアウトが構築できます。


まとめとブラウザ対応状況

CSS Grid の subgrid は、現在 Safari、Firefox、Chrome、Edge を含むすべての主要なモダンブラウザで完全にサポートされています(Can I Use においても完全な互換性が確認できます)。

これまでJavaScriptによる高さの監視や、Flexboxでのトリッキーなマージン調整で行っていたレイアウト修正は、subgrid によって過去のものとなりました。

カードデザインや複雑なコンポーネント内のアライメントを綺麗に整えたい場合は、ぜひ subgrid を活用したクリーンなCSS設計を取り入れてみてください。