Skip to Content
WebCSS모던 CSS08. 서브그리드로 카드 내부 정렬 맞추기

이번 편의 결과물: 06편의 카드 그리드 안에서 각 카드 내부(제목·설명·버튼)의 줄이 카드마다 흔들리지 않고 서브그리드로 나란히 맞춰집니다. 다루는 개념: grid-template-columns/rows: subgrid, 부모 트랙 상속 이유, 제목·설명·버튼 줄맞춤

이 편에서 만드는 파일

web-practice/portfolio/ └─ css/styles.css ~ (project-grid에 서브그리드 행 추가) web-practice/lessons/modern-css/ └─ 08_subgrid-card-alignment/ + (이번 편 스냅샷) └─ notes.md

개념 정리

06편에서 .project-grid를 그리드로, .project-card를 그 안의 그리드 아이템으로 만들었습니다. 문제는 카드 각각이 독립된 그리드라, 카드 1의 설명이 3줄이고 카드 2의 설명이 1줄이면 두 카드의 버튼 위치가 서로 어긋난다는 점입니다.

서브그리드는 자식 그리드가 자신만의 트랙을 새로 만들지 않고, 부모 그리드의 트랙을 그대로 물려받게 합니다.

grid-template-columns: subgrid자신의 열 트랙을 부모의 열 트랙 그대로 상속
grid-template-rows: subgrid자신의 행 트랙을 부모의 행 트랙 그대로 상속
전제 조건이 값을 쓰는 요소 자신이 부모 그리드의 그리드 아이템이어야 하고, grid-column/grid-row로 몇 개 트랙에 걸치는지 지정돼 있어야 함

부모가 “제목 행 · 설명 행 · 버튼 행” 세 종류의 행 트랙을 정의해 두면, 서브그리드로 상속받은 카드들은 같은 이름의 행에 내용이 몇 줄이든 그 행의 높이가 카드 전체 중 가장 큰 값으로 맞춰집니다. 이것이 부모 트랙을 상속해야 하는 이유입니다 — 각자 다른 그리드였다면 이 정렬이 카드마다 따로 계산되어 절대 맞을 수 없습니다.

흔한 오해: display: grid만 걸면 자동으로 부모와 정렬될 거라 생각하기 쉽지만, subgrid 값을 명시하지 않으면 자식은 완전히 새로운 독립 그리드를 만듭니다. 부모와 트랙을 공유하려면 반드시 subgrid라고 써야 합니다.

실습

1. 부모 그리드에 행 트랙 이름 정의하기

/* portfolio/css/styles.css */ @layer components { .project-grid { container-type: inline-size; container-name: cards; display: grid; grid-template-columns: 1fr; grid-auto-rows: auto; gap: var(--space-6); } @container cards (min-width: 480px) { .project-grid { grid-template-columns: repeat(2, 1fr); } } @container cards (min-width: 768px) { .project-grid { grid-template-columns: repeat(3, 1fr); } } }

카드 내부 행을 부모가 통제하려면, 카드 각각이 부모 그리드 안에서 몇 개의 행에 걸쳐 있는지부터 정해야 합니다. 다음 단계에서 부모에 명시적인 행 트랙 3개(제목·설명·버튼)를 만듭니다.

2. 카드를 서브그리드로 만들기

/* portfolio/css/styles.css */ @layer components { .project-grid { /* 카드 한 장당 제목·설명·버튼 3행을 명시적으로 정의 */ grid-template-rows: auto 1fr auto; grid-auto-flow: row; } .project-card { /* 이 카드가 부모의 행 트랙 3칸을 그대로 씀 */ display: grid; grid-row: span 3; grid-template-rows: subgrid; gap: var(--space-2); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius); padding: var(--space-4); } }

grid-row: span 3이 “이 카드는 부모의 행 트랙 3칸을 차지한다”는 뜻이고, grid-template-rows: subgrid가 “그 3칸을 내 자식(제목·설명·버튼)에게 그대로 물려준다”는 뜻입니다. 두 선언이 함께 있어야 서브그리드가 성립합니다.

3. 카드 내부 요소를 각 행에 배치하기

/* portfolio/css/styles.css */ @layer components { .project-card h2 { grid-row: 1; font-size: clamp(1rem, 6cqi, 1.375rem); } .project-card p { grid-row: 2; color: var(--color-text-muted); } .project-card button[data-open-project] { grid-row: 3; align-self: end; } }

grid-row: 1, 2, 3은 서브그리드가 상속한 부모의 행 번호를 그대로 가리킵니다. 07편에서 만든 @scope (.project-card) to (button[data-open-project]) 블록 안에 있는 h2·p·button[data-open-project] 규칙에 이 행 번호를 덧붙이는 것도 같은 효과를 냅니다 — 여기서는 .project-card 후손 선택자로 적어 두 편의 코드를 독립적으로 확인할 수 있게 했습니다. 이제 카드마다 설명 줄 수가 달라도, 2행(p)의 높이는 같은 그리드 라인에 걸린 모든 카드 중 가장 큰 값으로 통일되고, 3행(button[data-open-project])은 항상 그 아래 같은 위치에서 시작합니다.

4. 실행 및 확인

1. projects.html의 프로젝트 설명 텍스트 하나를 임시로 3~4줄까지 늘려 봅니다. 2. 브라우저에서 카드 그리드를 확인합니다 — 설명이 길어진 카드의 제목· 설명 영역만 세로로 늘어나고, 같은 행에 있는 다른 카드들의 버튼도 전부 같은 높이에서 시작해야 합니다. 3. 늘렸던 텍스트를 원래대로 되돌리고 다시 확인합니다.
  • 개발자 도구의 Grid 오버레이(레이아웃 탭)를 켜면 부모 트랙과 카드 트랙이 겹쳐 표시되어, 카드가 실제로 부모 트랙을 상속했는지 눈으로 확인할 수 있습니다.

직접 해보기

  1. grid-template-rows: auto 1fr auto의 가운데 값을 auto로 바꾸면 설명 영역이 내용 길이만큼만 차지하게 됩니다. 버튼 줄 정렬이 어떻게 달라지는지 관찰해 보세요.
  2. 태그 칩 목록(.project-card .tags)을 위한 행을 하나 더 추가해, 부모 그리드를 auto auto 1fr auto 4행으로 늘려 보세요.

풀이 보기

.project-grid { grid-template-rows: auto auto 1fr auto; } .project-card { grid-row: span 4; } .project-card h2 { grid-row: 1; } .project-card .tags { grid-row: 2; } .project-card p { grid-row: 3; } .project-card button[data-open-project] { grid-row: 4; }

행 개수를 바꾸면 grid-row: span N의 숫자와 자식들의 grid-row 번호를 함께 맞춰야 합니다.

자주 하는 실수

증상원인고치는 법
subgrid를 줬는데 트랙이 안 맞음grid-row: span N을 빠뜨려 카드가 몇 칸을 차지할지 정의 안 됨서브그리드를 쓰는 요소에 grid-row(또는 grid-column) span을 함께 지정한다
자식 요소가 행에 안 들어감자식에 grid-row 번호를 안 줘서 브라우저가 자동 배치함제목·설명·버튼 각각에 명시적 grid-row 번호를 지정한다
컨테이너 쿼리로 열 수가 바뀌면 서브그리드가 깨짐열 수 변경 규칙과 행 서브그리드 규칙이 서로 다른 값을 덮어씀@container 블록 안에서는 grid-template-columns만 바꾸고 grid-template-rows: subgrid는 그대로 유지한다
구형 Safari(16 미만)에서 레이아웃이 무너짐서브그리드가 2023-09 이전 버전에는 없음최신 Safari로 확인하거나 @supports (grid-template-rows: subgrid))로 폴백을 준비한다

확인 문제

문제 14지선다
자식 요소가 부모 그리드의 행 트랙을 그대로 상속하게 하는 값은
문제 24지선다
grid-template-rows: subgrid가 실제로 동작하기 위한 전제 조건은
문제 34지선다
카드마다 설명 줄 수가 달라도 버튼 위치를 나란히 맞추려는 목적에 서브그리드가 필요한 이유는

참고 자료

Last updated on