以前の記事(レイアウト手法の新しい武器になるCSSグリッドレイアウト入門)では、CSSグリッドレイアウトの基本的な使い方を紹介しました。グリッドレイアウトには、今回紹介するサブグリッドという機能もあります。サブグリッドを使うことで、親グリッドのトラック構造を子要素に継承させることができ、複雑なレイアウトをシンプルに実現できます。
この記事では、サブグリッドの基本的な仕組みと使い方を紹介します。グリッドレイアウトの基本については、前編の記事をあわせてご覧ください。
サブグリッドとは
サブグリッドとは、グリッドアイテムが親グリッドのトラック構造を引き継いで、自身もグリッドコンテナとして機能する仕組みです。grid-template-rowsまたはgrid-template-columnsの値にsubgridを指定することで利用できます。
親グリッドのトラックを子要素に継承する仕組み
通常、グリッドアイテムに対してdisplay: gridを指定して入れ子のグリッドを作成した場合、子グリッドは親グリッドとは独立したトラック構造を持ちます。そのため、親グリッドのトラックのサイズと子グリッドのトラックのサイズは連動しません。
サブグリッドを使用すると、子グリッドが親グリッドのトラックをそのまま引き継ぎます。親グリッドのライン番号やエリア名もそのまま利用でき、親子のグリッドが一体となって動作します。

ブラウザーの実装状況
サブグリッドの各ブラウザーの実装状況を確認すると、Chrome 117、Edge 117、Safari 16、Firefox 71以降でいずれも利用可能となっています。

サブグリッドの基本的な使い方
サブグリッドを使用するには、グリッドアイテムにdisplay: gridを指定した上で、grid-template-rowsまたはgrid-template-columnsの値にsubgridを指定します。
grid-template-rowsにsubgridを指定する
まず、親グリッドコンテナ側で行のトラックを定義します。
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, auto);
gap: 16px;
}
次に、グリッドアイテム(カード)側でサブグリッドを指定します。grid-rowで親グリッドの何行分を占有するかを指定し、grid-template-rows: subgridで親グリッドの行トラックを継承します。
.card {
display: grid;
grid-row: span 4; /* 親グリッドの4行分を占有 */
grid-template-rows: subgrid; /* 親グリッドの行トラックを継承 */
}
これにより、各カード内の子要素が親グリッドの行トラックに沿って配置されるようになります。テキスト量が異なるカードが並んでいても、対応する要素の縦位置が揃います。

grid-template-columnsにsubgridを指定する
行方向と同様に、列方向にもサブグリッドを適用できます。grid-template-columns: subgridを指定することで、親グリッドの列トラックを継承します。
.card {
display: grid;
grid-column: span 2; /* 親グリッドの2列分を占有 */
grid-template-columns: subgrid; /* 親グリッドの列トラックを継承 */
}

行方向・列方向の両方に同時にサブグリッドを適用することも可能です。
.card {
display: grid;
grid-row: span 4;
grid-column: span 2;
grid-template-rows: subgrid;
grid-template-columns: subgrid;
}
ギャップの継承
親グリッドにgapが設定されている場合、サブグリッドはそのギャップも継承します。
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, auto);
gap: 32px; /* このギャップがサブグリッドにも引き継がれる */
}
サブグリッド側で独自のgapを指定することで、親グリッドのギャップを上書きすることも可能です。
.card {
display: grid;
grid-row: span 4;
grid-template-rows: subgrid;
gap: 16px; /* 親グリッドのgapを上書き */
}

サブグリッドを使う上での注意点
サブグリッドを使う際に気をつけたいのが、カード内で使用する行数があらかじめ決まっている必要があるという点です。
通常のグリッドでは、アイテムの数が増えても暗黙のグリッドが自動的に作成されるため、行き場のない要素が生まれることはありません。しかし、サブグリッドでは親グリッドから継承したトラックの範囲内でのみ動作するため、暗黙のグリッドが作成されません。
例えば、3行分のトラックを継承したカードに4つ目の要素を追加した場合、4つ目の要素は新しい行に配置されるのではなく、最後の行(3行目)に重なって配置されてしまいます。

サブグリッドを使用する際は、カード内の要素数が一定であることを確認したうえで、必要な行数を親グリッド側で適切に定義するようにしましょう。
実践サブグリッド:カード型UI
ここまでの内容を踏まえて、実際のカード型UIにサブグリッドを適用してみます。cho-menの記事カードのような構成を例に考えてみましょう。

各カードは以下の3つの要素で構成されています。
テキスト量の異なるカードが横並びになる場合、サブグリッドを使わないと各要素の縦位置がカードごとにバラバラになってしまいます。
HTMLは以下のような構造を想定します。
<div class="grid-container">
<div class="card">
<img class="card-thumbnail" src="..." alt="...">
<h2 class="card-title">記事タイトル</h2>
<div class="card-meta">著者名 / 日付</div>
</div>
<div class="card">
<img class="card-thumbnail" src="..." alt="...">
<h2 class="card-title">記事タイトル</h2>
<div class="card-meta">著者名 / 日付</div>
</div>
...略
</div>
CSSは以下のように指定します。
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, auto);
gap: 32px 16px;
}
.card {
display: grid;
grid-row: span 3; /* 親グリッドの3行分を占有 */
grid-template-rows: subgrid; /* 親グリッドの行トラックを継承 */
}
親グリッドで3行分のトラックを定義し、各カードがgrid-row: span 3で3行分を占有します。grid-template-rows: subgridを指定することで、カード内の3つの要素がそれぞれ親グリッドの行トラックに沿って配置されます。
タイトルのテキスト量が異なるカードが並んでいても、サムネイル・タイトル・著者情報の縦位置がカード間で揃うようになります。

ポイントまとめ
- 親グリッドで
grid-template-rows: repeat(3, auto)のように行トラックを定義する。 - カード側で
grid-row: span 3を指定し、親グリッドの3行分を占有させる。 - カード側で
grid-template-rows: subgridを指定し、親グリッドの行トラックを継承する。 - これにより、テキスト量が異なるカード間でも、対応する要素の縦位置が揃う。
サブグリッドをレイアウトの引き出しに
本記事では、CSSサブグリッドの基本的な仕組みと使い方を、カード型UIを例に紹介しました。サブグリッドを使うことで、これまで実現が難しかった「複数カード間での要素の縦位置揃え」をシンプルなCSSで実現できます。
グリッドレイアウトの基本と組み合わせることで、より柔軟で整ったレイアウトを構築できるようになります。ぜひ、サブグリッドもレイアウト手法の引き出しのひとつとして活用してみてください。
参考資料
ウェブのお悩み、世路庵にご相談ください
ウェブ制作会社には、「言ったことしかやってくれない」「提案がない」といった不満を抱かれるケースがあります。目を引くようなビジュアルは作れるがビジネス理解が不足している、運用はしてもらえるがデザインやコーディングは外注に丸投げしている、といった体制では、しばしばプロジェクトが袋小路に迷い込んでしまいます。
世路庵は、ビジネスとクリエイティブを両立するウェブ制作会社です。ウェブサイトやウェブアプリケーションに課題を感じている方は、創業18年以上の経験と、業種・業態を選ばない1,000件以上の実績を持つ世路庵をぜひご検討ください。
合同会社世路庵