Subgrid

서브그리드

Lets a nested grid item inherit its parent grid's column/row tracks instead of defining its own.

Also known as: grid-template-columns: subgrid
···
html
<div class="wrap">
  <div class="badge" id="badge"><svg viewBox="0 0 10 10"><path id="bpath" d="M1.5 5.2l2.6 2.6L8.5 2.4" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg><span id="btext">확인 중</span></div>
  <div class="grid" id="grid">
    <div class="card"><div class="t">짧은 제목</div><div class="b">본문</div><button class="cta">더보기</button></div>
    <div class="card"><div class="t">두 줄까지 가는 긴 제목</div><div class="b">본문</div><button class="cta">더보기</button></div>
    <div class="card"><div class="t">제목</div><div class="b">본문</div><button class="cta">더보기</button></div>
  </div>
</div>
css
.wrap{position:relative;width:min(480px,94%)}
.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.card{display:grid;grid-row:span 3;grid-template-rows:subgrid;gap:6px;padding:10px;border:1px solid var(--line);border-radius:10px;background:var(--surface)}
.grid.fallback .card{grid-template-rows:44px 1fr 30px}
.t{font-size:12px;font-weight:700;color:var(--fg);line-height:1.3}
.b{font-size:11px;color:var(--muted)}
.cta{align-self:end;font-size:11px;font-weight:600;color:#fff;background:var(--accent);border:0;border-radius:6px;padding:5px 0}
.badge{position:absolute;top:-30px;right:0;display:flex;align-items:center;gap:5px;padding:4px 9px;border-radius:999px;font-size:10px;font-weight:700;background:var(--bg);border:1px solid var(--line);color:var(--accent-3)}
.badge.no{color:var(--accent-2)}
.badge svg{width:9px;height:9px}
js
const ok = CSS.supports('grid-template-columns', 'subgrid');
const b=document.getElementById('badge'),p=document.getElementById('bpath'),t=document.getElementById('btext');
b.classList.toggle('no', !ok);
p.setAttribute('d', ok ? 'M1.5 5.2l2.6 2.6L8.5 2.4' : 'M2 2l6 6M8 2l-6 6');
t.textContent = ok ? 'subgrid 지원됨' : '미지원 · 고정 높이 폴백';
if (!ok) document.getElementById('grid').classList.add('fallback');

Lining up a title/body/button row across several cards is awkward with plain grid — each card computes its own tracks, so if title heights differ, the button rows end up staggered. The classic fix was measuring every card's title height in JS and forcing them to the tallest one.

`grid-template-columns: subgrid` (or rows) lets a child grid inherit its parent's track lines instead of defining new ones. A single parent grid spanning multiple cards decides "this row is N px," and every child aligns to it automatically.

Check caniuse/MDN baseline for support. Without it, measuring element heights in JS and forcing a shared `min-height`, or falling back to table layout, are the usual workarounds.

When to use

Aligning internal rows (title/body/CTA) across a grid of cards down to the pixel.