CSS Subgrid — 중첩 그리드 정렬 문제를 푸는 방법
카드 그리드에서 내부 항목이 카드 간 정렬되지 않는 문제를 추가 마크업 없이 해결합니다. row/column subgrid의 정확한 사용법과 폼 정렬 패턴.
카드 안에 여러 줄의 정보(제목, 메타, 설명, 액션)가 있고, 카드 여러 개를 그리드로 배치할 때 — 각 카드 내부 항목들이 카드 간에 정렬되지 않는 문제가 자주 생깁니다. CSS subgrid는 부모 그리드의 트랙을 자식이 그대로 사용하게 해서, 이 정렬 문제를 추가 마크업 없이 해결합니다.
1. 문제 — 카드 내부 정렬이 어긋남
1<ul class="cards"> 2 <li><h3>긴 제목이 두 줄로 들어가는 카드</h3><p>본문</p><div>액션</div></li> 3 <li><h3>짧은 제목</h3><p>본문</p><div>액션</div></li> 4</ul>
각 카드 내부에서 display: grid로 auto auto auto 트랙을 만들면, 제목이 한 줄/두 줄인 카드 사이에서 본문 시작점이 어긋납니다. 카드별로 독립된 그리드라서 그렇습니다.
2. subgrid로 해결
부모 그리드를 row 트랙으로 정의하고, 자식이 grid-template-rows: subgrid로 그 트랙을 그대로 받습니다.
1.cards { 2 display: grid; 3 grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); 4 grid-template-rows: auto 1fr auto; 5 gap: 16px; 6} 7 8.cards > li { 9 display: grid; 10 grid-row: span 3; 11 grid-template-rows: subgrid; 12}
이제 모든 카드의 제목 영역, 본문 영역, 액션 영역이 정확히 정렬됩니다.
3. column subgrid
세로 정렬도 가능합니다. 폼 라벨/입력 정렬에 자주 씁니다.
1form { 2 display: grid; 3 grid-template-columns: 120px 1fr; 4} 5form > .row { 6 display: grid; 7 grid-template-columns: subgrid; 8 grid-column: 1 / -1; 9} 10form .row > label { grid-column: 1; } 11form .row > input { grid-column: 2; }
라벨 폭이 가장 긴 라벨에 맞춰 모든 행이 정렬됩니다. 별도 align-items나 고정 폭 없이.
4. flex만으로 안 되는 이유
flex로도 비슷하게 만들 수 있지만, "여러 카드 사이에 동일한 트랙"을 만들 수는 없습니다. flex는 한 컨테이너 안에서만 정렬 가능, subgrid는 부모/자식 그리드 사이의 트랙 공유를 가능하게 합니다.
5. 주의할 점
- subgrid는 부모가 grid여야 합니다. flex 부모에서는 동작하지 않습니다.
grid-template-columns: subgrid만 적용했다면 row는 여전히 독립이고, 반대도 마찬가지입니다. 둘 다 필요하면 둘 다 적용합니다.- 부모 트랙 수와 자식이 사용하려는 트랙 수가 맞아야 합니다.
grid-row: span 3처럼 명시하지 않으면 의도와 다른 영역으로 들어갈 수 있습니다. - 브라우저 지원: Chrome 117+, Safari 16+, Firefox 71+. 구형 브라우저는 일반 grid로 fallback 동작.
6. 정리
| 패턴 | 효과 |
|---|---|
grid-template-rows: subgrid | 카드 내부 행이 다른 카드와 정렬 |
grid-template-columns: subgrid | 폼 라벨/입력이 행마다 정렬 |
grid-row: span N | 자식이 부모 트랙 N개 사용 |
추가 마크업이나 고정 높이 hack 없이, 그리드의 본질인 "트랙 공유"를 자식까지 확장합니다. 카드 그리드 디자인이 한결 단정해집니다.
참고: MDN — Subgrid / W3C CSS Grid Level 2.