블로그 목록
frontend

CSS Subgrid로 카드 정렬 맞추기 — 제목 길이가 달라도 버튼이 한 줄로

카드 리스트를 만들다 보면 매번 걸리는 게 있다. 카드마다 제목 길이가 다르니까, 어떤 건 제목이 두 줄이고 어떤 건 한 줄이다. 그러면 그 아래 본문 시작 위치가 어긋나고, 맨 아래 버튼 높이도 제각각이 된다. 카드 하나하나는 멀쩡한데 나란히 놓으면 지저분해 보인다.

지금까지는 이걸 억지로 맞췄다. 제목에 min-height를 박아서 두 줄 높이만큼 강제로 확보하거나, JS로 제일 긴 제목 높이를 재서 나머지에 적용하거나. 둘 다 유지보수가 별로다. 폰트 바뀌면 min-height 다시 계산해야 하고, JS는 리사이즈마다 다시 재야 한다.

진짜 문제는 카드가 독립된 그리드라는 것

카드 안을 display: grid로 짜면 제목·본문·버튼이 각자 행을 갖는다. 근데 이 그리드는 카드 하나 안에서만 유효하다. 옆 카드의 제목 행과 내 카드의 제목 행은 아무 관계가 없으니까, 서로 높이를 맞출 방법이 없는 거다.

Subgrid는 이걸 해결한다. 바깥 리스트 그리드가 정한 행 높이를, 카드가 그대로 물려받게 만든다. 그러면 모든 카드의 제목 행이 같은 높이, 본문 행이 같은 높이가 된다.

코드

.card-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1rem;
}

.card {
  display: grid;
  /* 부모 그리드의 행 3개를 그대로 물려받는다 */
  grid-template-rows: subgrid;
  grid-row: span 3;
  gap: 0.5rem;
}

핵심은 두 줄이다. grid-template-rows: subgrid로 부모의 행 트랙을 상속받고, grid-row: span 3으로 이 카드가 부모 그리드에서 세 행을 차지한다고 선언한다. 카드 안 요소들(제목, 본문, 버튼)은 이 세 행에 하나씩 들어간다.

이제 부모 그리드가 각 행 높이를 카드 전체에서 제일 큰 콘텐츠 기준으로 잡아준다. 3번 카드 제목이 두 줄이면, 1·2번 카드 제목 행도 같이 두 줄 높이가 된다. 자연히 본문 시작점과 버튼 위치가 카드끼리 딱 맞는다.

정리

min-height나 JS 계산 없이, CSS 두 줄로 카드 정렬이 끝난다. Subgrid는 이제 크롬·사파리·파이어폭스 모두 지원(Baseline 2023)이라 프로덕션에 바로 써도 된다.

포인트는 딱 하나다. 정렬을 맞추고 싶은 요소들의 부모가, 바깥 그리드의 행(또는 열)을 상속받게 만들어라. 카드뿐 아니라 폼 라벨·입력칸 정렬, 테이블처럼 생긴 리스트에도 똑같이 통한다.