CSS Grid 완전 가이드: 반응형 2차원 레이아웃을 설계하는 법
title: "CSS Grid 완전 가이드: 반응형 2차원 레이아웃을 설계하는 법"
slug: "css-grid"
description: "CSS Grid의 행·열 기반 레이아웃, repeat()·minmax(), auto-fit과 auto-fill, 명시적·암시적 그리드, 접근성까지 실무 예제로 정리합니다."
tags: "CSS Grid, CSS, 반응형 웹, 웹 접근성, 프론트엔드"
CSS Grid: 행과 열을 함께 설계하는 반응형 레이아웃
카드 목록, 대시보드, 기사 본문처럼 “가로 몇 칸, 세로 몇 줄”이 동시에 중요한 화면은 한 방향으로 아이템을 배치하는 방식만으로 설명하기 어렵다. CSS Grid는 수평선과 수직선이 교차하는 2차원 그리드 위에 행과 열을 정의하고, 자식을 그 선과 영역에 배치하는 레이아웃 시스템이다. 그래서 페이지의 큰 구획에도, 카드 모음 같은 작은 UI에도 쓸 수 있다. display: grid를 선언하면 그 요소의 직계 자식이 grid item이 된다. Grid가 Flexbox를 대체한다는 뜻은 아니다. 한 축에서 정렬·분배가 핵심이면 Flexbox가 자연스럽고, 두 축의 선과 칸을 함께 설계해야 할 때 Grid가 특히 잘 맞는다.
첫 그리드와 grid-template-columns
grid-template-columns와 grid-template-rows는 개발자가 직접 정의한 트랙(track), 즉 인접한 두 grid line 사이의 공간을 만든다. fr은 고정 폭과 gap을 계산한 뒤 남은 공간을 비율로 나누는 단위다. 같은 폭 세 칸은 1fr 1fr 1fr보다 repeat(3, 1fr)가 읽기 쉽다. repeat()는 두 번째 인자로 받은 트랙 목록을 반복할 뿐이므로, repeat(4, 1fr 2fr)처럼 패턴 자체도 반복할 수 있다.
다음 예제는 화면 폭에 맞춰 카드를 여러 열로 배치한다. 각 열은 16rem보다 작아지지 않고, 남는 폭은 1fr로 나눠 가진다. 브라우저에서 HTML과 CSS를 함께 저장해 바로 실행할 수 있다.
<section class="products" aria-label="추천 기사">
<article><h2>Grid 입문</h2><p>행과 열을 함께 다룹니다.</p></article>
<article><h2>반응형 카드</h2><p>폭에 따라 열 수가 바뀝니다.</p></article>
<article><h2>접근 가능한 순서</h2><p>읽는 순서를 보존합니다.</p></article>
<article><h2>명시적 배치</h2><p>필요한 곳에만 씁니다.</p></article>
</section>
* { box-sizing: border-box; }
.products {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: 1rem;
max-width: 72rem;
margin-inline: auto;
padding: 1rem;
}
.products > article {
padding: 1rem;
border: 1px solid #cbd5e1;
border-radius: .75rem;
background: #fff;
}
minmax(최소값, 최대값)은 트랙 크기의 범위를 지정한다. 위의 minmax(16rem, 1fr)은 카드가 지나치게 좁아지는 것을 막고, 더 넓은 컨테이너에서는 열이 함께 늘어나게 한다. 다만 긴 단어·큰 이미지·최소 콘텐츠 크기가 있는 실제 콘텐츠에서도 원하는 폭과 줄바꿈이 나오는지 확인해야 한다. minmax()는 grid-template-columns, grid-template-rows, grid-auto-columns, grid-auto-rows에서 사용할 수 있다.
auto-fit과 auto-fill은 빈 칸 처리에서 다르다
둘 다 컨테이너에 들어가는 만큼 반복 트랙을 계산한다. 차이는 아이템을 놓은 뒤에 나타난다. auto-fill은 들어갈 수 있는 빈 트랙도 유지한다. 반면 auto-fit은 아이템이 없는 반복 트랙을 0px로 접어(collapsed) 남은 아이템이 더 넓게 퍼질 수 있게 한다. 카드가 적을 때 마지막 카드가 남은 폭을 사용하게 하려면 보통 auto-fit이 편하다. 빈 열의 규칙적인 리듬이나 명명한 선을 계속 유지해야 하는 설계라면 auto-fill이 더 알맞을 수 있다. 둘 중 하나가 항상 “반응형에 더 좋다”는 규칙은 없다. 콘텐츠 개수와 빈 공간의 의도를 기준으로 실제 폭에서 비교하자.
명시적 그리드와 암시적 그리드
grid-template-columns: repeat(3, 1fr)처럼 선언한 열·행은 명시적(explicit) grid다. 그런데 네 번째, 다섯 번째 카드가 들어오면 브라우저는 콘텐츠를 담기 위한 행을 자동으로 더 만든다. 이것이 암시적(implicit) grid다. 기본 암시적 트랙은 내용과 남은 공간의 영향을 받아 자동 크기가 된다. 목록의 행 높이를 일정 범위로 관리하려면 다음처럼 grid-auto-rows를 명시한다.
.dashboard {
display: grid;
grid-template-columns: 15rem 1fr;
grid-template-rows: auto;
grid-auto-rows: minmax(8rem, auto);
gap: 1rem;
}
.dashboard__summary { grid-column: 1 / -1; }
grid-column: 1 / -1은 첫 번째 열선부터 마지막 열선까지 영역을 넓힌다. 이런 명시적 배치는 헤더, 요약, 사이드바처럼 구조적 이유가 분명한 요소에 쓰면 읽기 좋다. 모든 카드를 좌표로 고정하면 데이터가 늘거나 화면이 좁아질 때 유지보수가 어렵다. 먼저 자동 배치를 믿고, 정말 필요한 요소에만 선 번호·이름·영역을 부여하는 편이 안정적이다.
레이아웃보다 먼저 지켜야 할 순서와 접근성
Grid는 화면에 보이는 위치를 바꿀 수 있지만 DOM의 읽기 순서, 키보드 탐색 순서, 스크린 리더의 탐색 순서는 대체로 HTML 소스 순서를 따른다. CSS Grid 명세도 보조 기술과 순차 탐색의 논리 순서가 시각적 순서와 어긋나지 않게 하라고 권고한다. 따라서 모바일에서 먼저 읽어야 할 내용을 HTML 앞에 두고, 데스크톱 모양을 맞추려 grid-column, grid-row, order로 대규모 재정렬하는 방식은 피하자. 특히 grid-auto-flow: dense는 빈 공간을 메우기 위해 뒤의 아이템을 시각적으로 앞 칸에 넣을 수 있으므로, 순서가 의미를 갖는 카드·폼·상품 목록에는 신중해야 한다.
의미 있는 구조는 HTML로 만든다. 기사에는 article, 목록에는 ul/li, 버튼에는 button, 링크에는 a를 쓰고, gap으로 간격을 만들면 장식용 여백 요소도 줄어든다. 포커스가 보이는지, 200% 확대와 좁은 폭에서 콘텐츠가 잘리지 않는지, 키보드로 소스 순서대로 이동하는지를 테스트하자. CSS Grid의 핵심 기능은 현대 브라우저에서 널리 구현되어 있지만, 지원 범위는 사용하는 세부 기능과 지원 대상 브라우저에 따라 다르다. 배포 전 MDN 호환성 표와 실제 대상 기기에서 확인하는 습관이 가장 안전하다.
Grid는 “열을 예쁘게 여러 개 만드는 문법”보다 넓은 도구다. 트랙의 최소·최대 크기, 자동 생성되는 행, 소스 순서라는 제약을 함께 설계할 때, 반응형 화면이 콘텐츠 변화에도 덜 흔들린다.