Flexbox가 1차원(행 또는 열) 레이아웃을 다룬다면, CSS Grid는 행과 열을 동시에 제어하는 2차원 레이아웃 시스템입니다. 복잡한 페이지 레이아웃을 float이나 position 없이 깔끔하게 구현할 수 있습니다.
Grid 기본 개념
.container {
display: grid;
/* 3개의 열: 각각 1fr(가용 공간의 1/3) */
grid-template-columns: 1fr 1fr 1fr;
/* 단축: repeat(3, 1fr) */
/* 행 높이 자동 (내용에 맞춤) */
grid-template-rows: auto;
/* 셀 간격 */
gap: 1rem;
/* row-gap: 1rem; column-gap: 2rem; 로 개별 설정 가능 */
}
fr 단위와 고정 크기 혼합
.layout {
display: grid;
/* 사이드바 240px 고정, 나머지는 메인 영역 */
grid-template-columns: 240px 1fr;
/* 헤더 64px, 본문 자동, 푸터 60px */
grid-template-rows: 64px 1fr 60px;
min-height: 100vh;
gap: 0;
}
grid-template-areas — 이름으로 배치
레이아웃을 ASCII 아트처럼 직관적으로 정의할 수 있습니다.
.page {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: 64px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
아이템 배치 제어
/* 특정 아이템이 여러 셀을 차지하게 하기 */
.featured {
grid-column: 1 / 3; /* 1번 줄부터 3번 줄까지 (2칸) */
grid-row: 1 / 3; /* 1번 줄부터 3번 줄까지 (2행) */
}
/* span 키워드 사용 */
.wide { grid-column: span 2; } /* 2칸 차지 */
.tall { grid-row: span 3; } /* 3행 차지 */
반응형 그리드 — auto-fill & minmax
화면 크기에 따라 자동으로 열 수가 조정되는 반응형 그리드를 미디어 쿼리 없이 구현할 수 있습니다.
.card-grid {
display: grid;
/* 최소 280px, 최대 1fr로 자동으로 열 수 결정 */
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
/* auto-fill: 공간이 남아도 빈 셀 유지 */
/* auto-fit: 남는 공간을 기존 아이템이 채움 */
정렬 제어
.grid {
display: grid;
grid-template-columns: repeat(3, 200px);
/* 전체 그리드 정렬 (컨테이너 기준) */
justify-content: center; /* 가로 */
align-content: center; /* 세로 */
/* 셀 내부 아이템 정렬 */
justify-items: center;
align-items: center;
}
/* 개별 아이템 정렬 오버라이드 */
.special {
justify-self: end;
align-self: start;
}
실전: 블로그 카드 그리드
.posts-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 1.5rem;
}
/* 첫 번째 카드를 가로 전체로 */
.post-card:first-child {
grid-column: 1 / -1; /* -1은 마지막 줄 */
display: grid;
grid-template-columns: 1fr 1fr;
}
@media (max-width: 768px) {
.post-card:first-child {
grid-template-columns: 1fr;
}
}
subgrid — 중첩 그리드 정렬
CSS Grid Level 2에서 도입된 subgrid를 사용하면 자식 그리드가 부모 그리드의 트랙을 그대로 상속할 수 있습니다. 카드 컴포넌트 내부의 요소들을 그리드 전체에 맞춰 정렬할 때 특히 유용합니다.
/* 부모 그리드 */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto; /* 제목 / 내용 / 버튼 */
gap: 1.5rem;
}
/* 각 카드가 부모의 행 구조를 상속 */
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
}
/* 이제 모든 카드의 제목, 내용, 버튼 높이가 맞춰집니다 */
.card-title { grid-row: 1; }
.card-body { grid-row: 2; }
.card-footer { grid-row: 3; align-self: end; }
크롬 117+, 파이어폭스 71+, 사파리 16+에서 지원됩니다. 2026년 기준 주요 브라우저에서 모두 사용할 수 있습니다.
CSS Grid 실전 적용 팁
Grid를 처음 배울 때 헷갈리기 쉬운 부분과 실무에서 자주 쓰는 패턴을 정리했습니다.
- dense 키워드 —
grid-auto-flow: dense를 추가하면 빈 공간을 자동으로 채워 핀터레스트 스타일의 마소너리(masonry) 레이아웃과 유사한 효과를 낼 수 있습니다. - place-items 단축 속성 —
place-items: center는align-items: center; justify-items: center와 같습니다. 가운데 정렬 코드를 한 줄로 줄일 수 있습니다. - 브라우저 DevTools 활용 — Chrome과 Firefox의 DevTools에는 Grid 오버레이 기능이 있습니다. 라인 번호와 영역 이름을 시각적으로 확인할 수 있어 레이아웃 디버깅에 큰 도움이 됩니다.
- 고정 열 + 반응형 혼합 —
grid-template-columns: 240px minmax(0, 1fr)처럼 사이드바는 고정하고 메인 콘텐츠는 유동적으로 설정하면, 미디어 쿼리를 최소화하면서도 다양한 화면 크기를 커버할 수 있습니다.
카드 목록, 대시보드, 전체 페이지 레이아웃처럼 2차원 배치가 필요하면 Grid를 사용하세요. 네비게이션 바, 버튼 그룹처럼 1차원 정렬이 목적이면 Flexbox가 적합합니다. 둘을 함께 사용하는 것이 가장 실용적인 선택입니다. Grid로 전체 페이지 뼈대를 잡고, 각 영역 내부는 Flexbox로 정렬하는 패턴이 현업에서 가장 많이 쓰입니다.
이름 있는 그리드 라인
grid-template-areas 외에도 라인에 직접 이름을 붙여 배치에 활용할 수 있습니다. 특히 복잡한 레이아웃에서 코드 가독성이 높아집니다.
.layout {
display: grid;
grid-template-columns:
[sidebar-start] 240px
[sidebar-end content-start] 1fr
[content-end];
grid-template-rows:
[header-start] 64px
[header-end main-start] 1fr
[main-end footer-start] 60px
[footer-end];
}
.sidebar { grid-column: sidebar-start / sidebar-end; }
.main { grid-column: content-start / content-end; }
CSS Grid로 미디어 쿼리 없는 반응형 레이아웃
auto-fill과 minmax를 조합하면 미디어 쿼리 없이도 화면 너비에 따라 컬럼 수가 자동으로 조절됩니다.
/* 최소 280px, 이상은 1fr — 화면 너비에 따라 자동으로 3열→2열→1열로 변경 */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
/* 카드가 1개뿐일 때 꽉 채우지 않도록 */
.card-grid:has(:only-child) .card {
max-width: 400px;
}
이 패턴은 미디어 쿼리 없이도 640px 이하에서는 1열, 768px에서는 2열, 1200px 이상에서는 4열이 되도록 자동 조정됩니다. 반응형 카드 그리드의 가장 실용적인 구현 방법으로, 대부분의 상황에서 이 패턴 하나로 충분합니다.
Grid 레이아웃 디버깅
Chrome과 Firefox의 DevTools에는 CSS Grid 전용 오버레이 도구가 내장되어 있습니다.
- Chrome — Elements 패널 → 요소 선택 → Styles 탭의 grid 옆 격자 아이콘 클릭. 라인 번호, 트랙 크기, 영역 이름이 화면에 표시됩니다.
- Firefox — Inspector 탭 → Layout 패널에서 Grid 섹션 확인. 여러 그리드를 동시에 오버레이할 수 있어 중첩 레이아웃 디버깅에 탁월합니다.
Grid 레이아웃 문제는 대부분 라인 번호를 시각적으로 확인하면 즉시 원인을 찾을 수 있습니다. DevTools 오버레이를 적극 활용하면 디버깅 시간을 크게 줄일 수 있습니다.
CSS Grid와 Flexbox를 함께 쓰는 전략
CSS Grid와 Flexbox는 서로 경쟁 관계가 아닙니다. 두 레이아웃 방식은 각각 잘 하는 영역이 다르기 때문에, 실무에서는 함께 사용하는 것이 가장 효과적입니다. Grid는 페이지 전체 레이아웃이나 복잡한 이차원(가로×세로) 배치에 강합니다. 헤더, 사이드바, 메인 콘텐츠, 풋터를 배치하는 페이지 레벨 레이아웃은 Grid로 작성하면 코드가 직관적이고 관리하기 쉽습니다. Flexbox는 단일 방향(가로 또는 세로)의 배치에 강합니다. 내비게이션 메뉴 아이템을 가로로 정렬하거나, 카드 내부의 아이콘과 텍스트를 세로 중앙 정렬하는 컴포넌트 레벨 작업이 여기에 해당합니다.
실무에서 자주 쓰이는 패턴은 Grid로 외부 레이아웃을 잡고, Grid 셀 내부에서 Flexbox로 콘텐츠를 정렬하는 조합입니다. 예를 들어 상품 목록 페이지를 Grid로 카드 배치를 하고, 각 카드 내부에서는 이미지, 제목, 가격, 버튼을 Flexbox로 세로 정렬하는 방식입니다. 두 방식을 상황에 맞게 선택하는 기준은 간단합니다. "두 축을 동시에 제어해야 한다면 Grid, 한 축만 다룬다면 Flexbox"로 시작해서 익숙해지면 더 섬세한 판단을 내릴 수 있게 됩니다. CSS Grid가 처음에는 생소하게 느껴지더라도, 기본 속성 몇 가지를 익히고 나면 이전에 float이나 position으로 해결하던 복잡한 레이아웃을 훨씬 간단하게 구현할 수 있어 생산성이 크게 향상됩니다.