はじめに
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設計を取り入れてみてください。
