- subgridとは?:入れ子レイアウトの“ズレ問題”を解決する救世主
- そもそもsubgridって何?
- 具体例で理解する subgrid
- subgridを使う際の注意点
- grid-template-areas の応用:エリア指定で“重ね”を実現する
- position なしでレイヤーを作る
- grid-template-areas を使うメリット
- subgrid × areas で作る:実務用カード型レイアウト
- カード型UIの課題
- コピペOKの実用コード
- 応用例:メディア型レイアウト(画像+文章)
- よくあるメディア型のレイアウト
- コピペOKの実用コード
- まとめ
- ① subgridを使って入れ子レイアウトのズレを解消する
- ② grid-template-areasの応用で“重ねるレイアウト”が作れる
- ③ subgrid × グリッドで実用的なカード型レイアウトを実装
- display: grid は、基本を押さえればここまで表現できる
- さいごに
subgridとは?:入れ子レイアウトの“ズレ問題”を解決する救世主
そもそもsubgridって何?
subgridは、親グリッドの行・列サイズを、子グリッドでもそのまま共有する仕組みです。
よくある例として、カードUIでタイトルの長さが異なると、ボタン位置が揃わない問題があります。

subgrid を使うと、このズレを簡単に解消できます。
具体例で理解する subgrid
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1.5rem;
}
.card {
display: grid;
grid-template-rows: subgrid; /* ← 親の行を共有 */
grid-row: span 4; /* 4つの行を使う */
gap: .75rem;
}
上記がサブグリッドのcssとなります。
グリッドアイテムに対して、display: grid; とgrid-template-rows: subgrid; を使うことで、サブグリッドを定義できます。サブグリッド定義時には、grid-rowでどれだけの数を使うかということも明記が必要です。
こうすることで、グリッドアイテム間の行の高さが連動するので、タイトルが長いものがあっても、その後の文章の開始位置などが一致するため、より統一感を持たせることができます。
subgridを使う際の注意点
containerクエリと相性が悪い
親のグリットコンテナーや、グリッドアイテムにcontainer-type: inline-size;などコンテナークエリを指定していると、はサブグリッドは効かなくなります。
.parent {
display: grid;
grid-template-columns: 1fr 2fr;
container-type: inline-size; /* ← つけた瞬間 subgrid 不可 */
}
.child {
container-type: inline-size; /* ← これも subgrid 不可 */
display: grid;
grid-template-columns: subgrid; /* ← Safari/Chrome で効かない */
}
個人的に結構困るポイントです。カードアイテムの幅に対して、中の文字サイズをcqiで組みたいと思った時にうまく効かず時間溶かしました。。。
subgrid は “1階層上の親” からしか継承できない
直属の親要素がdisplay: grid;でないと指定ができません。もし、間にラッパーなど挟んでいる場合は、display: contents;でコンテンツ化する必要がございます。display: contents;も表示が不安定になる原因によくなるので、あまりお勧めはできません。
gap は “親の gap をそのまま継承する”
親のgap指定をサブグリッドを指定すると継承します。ただ、グリッドアイテム(サブグリッド側)でgap: 0;など上書きで対応が可能です。
grid-template-areas の応用:エリア指定で“重ね”を実現する
position なしでレイヤーを作る
要素が重なっているレイアウト。よくあると思います。
positionを使わずに、gridだけで要素を重ねることができます。
.hero {
display: grid;
grid-template-areas: "stack";
}
.hero__img {
grid-area: stack;
}
.hero__text {
grid-area: stack;
}
グリッドアイテムに同じgrid-area: stack;を指定することで、重ねることができます。positionだとabsoluteを使うため、要素があっち行ったりこっち行ったりレスポンシブで崩れやすいという点がありますが、gridだと崩れにくい重なりレイアウトが可能です。
grid-template-areas を使うメリット
- レスポンシブで崩れにくい重なりレイアウトが可能
- 親のグリッドコンテナーの
grid-template-aresをメディアクエリで変更するだけで、PCでは横並び、SPでは重なりというレイアウト切り替えが非常に簡単
subgrid × areas で作る:実務用カード型レイアウト
カード型UIの課題
カード型のレイアウトで以下の点でよく困りませんか?
- タイトルの行数が違うと高さが揃わない
- ボタンの位置がバラバラになる
- 画像の高さが揃わなくて崩れる
- flex だと対応が難しいパターンがある
最初のsubgridの説明で少し述べましたが、subgrid でこれを解決できます。
コピペOKの実用コード
<ul class="card-list">
<li class="card">
<h3 class="card__title">タイトルが入ります</h3>
<img src="img/sample1.jpg" alt="サンプル画像" class="card__img" />
<p class="card__text">
説明文がここに入ります。複数行になっても subgrid のおかげで
全カードの高さがキレイに揃います。
</p>
<a href="#" class="card__btn">詳しく見る</a>
</li>
<li class="card">
<h3 class="card__title">別のカードタイトル</h3>
<img src="img/sample2.jpg" alt="サンプル画像" class="card__img" />
<p class="card__text">文章が短めのパターン。</p>
<a href="#" class="card__btn">詳しく見る</a>
</li>
<li class="card">
<h3 class="card__title">もうひとつのタイトル</h3>
<img src="img/sample3.jpg" alt="サンプル画像" class="card__img" />
<p class="card__text">
文章が長くなるとこんな感じになります。subgrid により…以下略
</p>
<a href="#" class="card__btn">詳しく見る</a>
</li>
</ul>
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1.5rem;
}
.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 4;
gap: .75rem;
}
.card__img {
grid-row: 1;
}
.card__title {
grid-row: 2;
}
.card__text {
grid-row: 3;
}
.card__btn {
grid-row: 4;
justify-self: end; /* ← ボタンだけ右寄せしたい場合に便利 */
}
実装後のイメージ

cssについて最小限しか書いていません。text-align: left;などは省略しています。
マークアップでimgタグよりも先にh3タグを書いたのは、スクリーンリーダーを利用する方に向けて、まずはアイテムの見出しを読み上げてもらわないと何についての画像かがわからないため、imgタグよりも先にh3タグをマークアップしています。
.card__btnで指定したjustify-self: end;これはアイテム個別でどこに配置するかを指定できるプロパティです。他にもpタグでaタグを囲って、pタグにtext-align: right;をつけたり方法はありますが、知っていれば便利なプロパティです。
応用例:メディア型レイアウト(画像+文章)
よくあるメディア型のレイアウト
メディア型のレイアウトで、PCでは画像とテキストを横並び、SPでは縦並びにしたい場合、gird-template-areasを使うと便利です。
コピペOKの実用コード
<ul class="media-list">
<li class="media">
<h3 class="media__title">サンプルタイトルA</h3>
<figure class="media__thumb">
<img src="img/sample1.jpg" alt="サンプル画像A" />
</figure>
<p class="media__meta">2025.12.02 / カテゴリーA</p>
<p class="media__text">
こちらはサンプルテキストAです。ダミーとして適当な文章を入れています。
実際のコンテンツに差し替えてご利用ください。
</p>
<a href="#" class="media__btn">詳しく見る</a>
</li>
<li class="media">
<h3 class="media__title">サンプルタイトルB</h3>
<figure class="media__thumb">
<img src="img/sample2.jpg" alt="サンプル画像B" />
</figure>
<p class="media__meta">2025.11.28 / カテゴリーB</p>
<p class="media__text">
サンプルテキストBです。説明文の長さがばらつかないように、
あらかじめ整えた文章を入れています。
</p>
<a href="#" class="media__btn">詳しく見る</a>
</li>
<li class="media">
<h3 class="media__title">サンプルタイトルC</h3>
<figure class="media__thumb">
<img src="img/sample3.jpg" alt="サンプル画像C" />
</figure>
<p class="media__meta">2025.10.01 / カテゴリーC</p>
<p class="media__text">
サンプルテキストCです。これは仮の文章として設定しています。
デザイン確認やレイアウト調整にご活用ください。
</p>
<a href="#" class="media__btn">詳しく見る</a>
</li>
</ul>
.media-list {
display: grid;
grid-template-columns: 1fr; /* SP では 1 カラム */
gap: 1.5rem;
max-width: 1200px;
margin-inline: auto;
grid-auto-rows: auto; /* subgrid の親になる行トラック */
}
/* PC で 2 カラムにする */
@media (min-width: 768px) {
.media-list {
grid-template-columns: 1fr 1fr;
}
}
/* 各アイテム全体(カード) */
.media {
display: grid;
grid-template-columns: 1fr; /* SP では縦一列 */
grid-template-rows: subgrid; /* 親 .media-list の行構造を共有 */
grid-row: span 5; /* 画像+テキスト4つ = 5行分を使う */
gap: 0.75rem 1.5rem;
padding: 1.25rem;
border: 1px solid #ddd;
border-radius: 0.75rem;
background-color: #fff;
}
/* スマホでは縦並び(画像 → テキスト) */
.media__thumb {
grid-column: 1 / 2;
grid-row: 1 / 2;
margin: 0;
width: 100%;
aspect-ratio: 1.6 / 1;
}
.media__thumb img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 0.5rem;
}
/* 各要素を「どの行に置くか」指定しておく */
.media__title {
grid-column: 1 / 2;
grid-row: 2 / 3;
font-size: 1.1rem;
font-weight: 600;
}
.media__meta {
grid-column: 1 / 2;
grid-row: 3 / 4;
font-size: 0.85rem;
color: #666;
}
.media__text {
grid-column: 1 / 2;
grid-row: 4 / 5;
font-size: 0.9rem;
line-height: 1.7;
}
.media__btn {
grid-column: 1 / 2;
grid-row: 5 / 6;
justify-self: end; /* ボタンだけ右寄せ */
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.4rem 0.9rem;
border-radius: 999px;
background-color: #08254f;
color: #fff;
font-size: 0.85rem;
text-decoration: none;
}
/* PC では「画像+テキスト」を横並びにする */
@media (min-width: 768px) {
.media {
grid-template-columns: 220px 1fr; /* 左: サムネ, 右: テキスト */
grid-template-rows: subgrid; /* 親の行トラックを 4 本共有 */
grid-row: span 4; /* 右側は 4 行(タイトル〜ボタン) */
}
.media__thumb {
grid-column: 1 / 2;
grid-row: 1 / 5; /* 1〜4行を縦にまたぐ(左の帯) */
aspect-ratio: 1 / 1;
}
.media__title {
grid-column: 2 / 3;
grid-row: 1 / 2;
}
.media__meta {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.media__text {
grid-column: 2 / 3;
grid-row: 3 / 4;
}
.media__btn {
grid-column: 2 / 3;
grid-row: 4 / 5;
}
}
実装後のイメージ

長いcssになっていますが、ポイントとしては以下です。
- liタグの直下の要素ににsubgridを指定する。
- PCの場合は2列になるため、grid-row: span 4;と画像を省いた4行を指定し、SPの場合は1列のため、grid-row: span 5;を指定する。
- grid-column, grid-rowでどのマスにはめ込むかを指定する。
まとめ
今回の記事では、display: grid の中でも 「もう一歩先」 のレイアウトを作るうえで欠かせないテクニックを紹介しました。
特に注目したのは以下の3点です。
① subgridを使って入れ子レイアウトのズレを解消する
subgrid は、
「親グリッドの行・列構造をそのまま子要素でも共有できる」
という、これまでの CSS にはなかった強力な仕組みです。
- タイトルの行数が違っても高さが揃う
- カードボタンの位置がズレない
- デザインカンプ通りの整列がしやすい
と、実案件でのメリットが非常に大きいテクニックでした。
② grid-template-areasの応用で“重ねるレイアウト”が作れる
grid はマス目に配置するだけではなく、
同じエリア名を割り当てることで複数要素を簡単に重ねる
という表現もできます。
position を使わないぶんレスポンシブに強く、
ヒーローセクション・バナー・装飾要素などで役立つ技術です。
③ subgrid × グリッドで実用的なカード型レイアウトを実装
記事では、実案件でも頻出する
- 画像
- タイトル
- テキスト
- ボタン
の「カード型レイアウト」を例に、
subgrid で高さが揃って崩れない UI を実装しました。
- タイトルが長くても見た目が揃う
- ボタン位置もピタッとそろう
- grid だけで完結するためメンテナンス性が高い
という、“実務レベルで使える形” に落とし込んでいます。
display: grid は、基本を押さえればここまで表現できる
このシリーズ(基礎 → 応用① → 応用②)で扱った内容をマスターすると、
- 一覧レイアウト
- カード型UI
- メディア型レイアウト
- LPの複雑な配置
- position なしの重ね表現
といった 現場でよくあるレイアウトは、ほぼ grid で対応できるようになります。
さいごに
display: grid は、慣れてくると「デザインカンプをそのままCSSで再現する」ための最強ツールになります。
今回紹介した subgrid や areas の応用は、まさにその強みを最大限活かせるテクニックだと思います。

