Flexbox가 한 방향(가로 또는 세로)의 레이아웃을 다룬다면, Grid는 행과 열을 동시에 정의하는 2차원 레이아웃이다. 신문 지면처럼 칸을 나눠 콘텐츠를 배치하고 싶을 때 Grid가 적합하다.
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
.container {
display: grid;
grid-template-columns: 200px 200px 200px; /* 3열, 각 200px */
grid-template-rows: 100px 100px; /* 2행, 각 100px */
}

fr(fraction)은 그리드에서 사용 가능한 공간의 비율을 나타내는 단위다.
.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
/* 전체를 4등분 → 1/4, 2/4, 1/4 */
}
px와 fr을 섞어 쓸 수도 있다.
grid-template-columns: 200px 1fr;
/* 첫 열은 200px 고정, 나머지를 두 번째 열이 차지 */
같은 크기의 열이나 행을 반복할 때 쓴다.
.container {
grid-template-columns: repeat(3, 1fr);
/* 1fr 1fr 1fr 과 동일 */
grid-template-columns: repeat(4, 200px);
/* 200px 200px 200px 200px */
}
.container {
gap: 16px; /* 행·열 모두 16px */
row-gap: 20px; /* 행 간격만 */
column-gap: 12px; /* 열 간격만 */
}
컨테이너 너비에 맞게 열 수를 자동으로 조절한다. 반응형 그리드를 만들 때 유용하다.
.container {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
minmax(200px, 1fr) — 최소 200px, 최대 1frauto-fill — 빈 칸이 생겨도 자리를 유지auto-fit — 남는 공간을 기존 아이템이 채움아이템이 몇 번 선(grid line)부터 몇 번 선까지 차지할지 지정한다.
.item-a {
grid-column: 1 / 3; /* 1번 선 ~ 3번 선 (2열 차지) */
grid-row: 1 / 2; /* 1행 */
}
.item-b {
grid-column: span 2; /* 현재 위치에서 2열 차지 */
}

이름으로 레이아웃 구조를 정의하는 직관적인 방법이다.
.container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
| 구분 | Flexbox | Grid |
|---|---|---|
| 차원 | 1차원 (가로 또는 세로) | 2차원 (가로 + 세로) |
| 기준 | 콘텐츠 크기 기반 | 고정 트랙(행/열) 기반 |
| 적합한 상황 | 네비게이션, 버튼 그룹, 카드 한 줄 | 페이지 레이아웃, 갤러리, 대시보드 |
둘은 경쟁 관계가 아니다. 페이지 전체 레이아웃은 Grid로 잡고, 그 안의 컴포넌트 배치는 Flexbox로 하는 식으로 함께 쓴다.
Grid의 핵심은 "행과 열을 먼저 정의하고, 아이템을 그 위에 올린다"는 사고방식이다. 익숙해지면 복잡한 레이아웃도 코드 몇 줄로 표현된다.