CSS Grid | 그리드 레이아웃 완벽 가이드
이 글의 핵심
CSS Grid: 그리드 레이아웃 Grid 기본 개념·Grid Template Columns/Rows.
HTML/CSS 시리즈 #06 · CSS Grid
솔직히 말하면, 페이지 뼈대·대시보드·갤러리는 Grid가 답이야. Flexbox? 한 줄(가로 또는 세로) 흐름엔 잘 맞는데, 1차원이라 “몇 열·몇 행”을 동시에 잡는 건 늘 애매해진다. Grid는 2차원—행(row) + 열(column)을 한 번에 설계하는 도구다. (너희 팀이 “플렉스로만” 하다 퍼센트·마이너스 마진 지옥 본 경험 있지?)
Grid 디버깅으로 하루…
어느 날 대시보드 grid-template-areas 짠 다음, 뷰포트 줄였더니 sidebar가 갑자기 맨 밑에 가 있는 거야. “내가 areas 잘못 썼나?” 싶어서 DevTools Layout → Grid 켰더니, 열·행 라인 번호가 눈에 박힌다. grid-column: 1 / -1이 진짜 어디를 가리키는지, span이 자동 배치랑 충돌한 건 아닌지, 한 줄씩 뜯으면서 맞췄지. min-width: 0 안 준 카드가 셀을 밀어서 fr이 이상해 보였던 것도, 그날 grid 오버레이 켜고 처음 알았다. 하루 쓴 거 같지만, 그때부터 “일단 grid 켜고 선부터 본다”가 습관이 됐어.
구식 float + clearfix 대신, 의도는 이렇게 쓰는 쪽이 낫다.
/* 레거시 */
.col-4 { float: left; width: 33.33%; }
/* 의도가 바로 읽힘 */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
2차원 잡는다 = 명시적 트랙·gap·(필요하면) areas. Flex로만 역할 바꿔 쓰다 보면 “한 줄” 사고에 갇힌다. Grid가 답, Flexbox는 1차원—이 조합(바깥 Grid, 안 Flex) 머리에 박아 두면 편하다.
언제 뭘 쓸지 (표 말고 그림)
Flex에 잘 맞는 것: [툴바 ············ 버튼들 →→→ ]
(한 축, 한 줄 흐름)
Grid에 잘 맞는 것: ┌────┬────┬────┐
│ H │ H │ H │ ← 행+열 동시
├────┼────┼────┤
│ S │ M │ M │
└────┴────┴────┘
- 네비·툴바·버튼 한 줄 → Flex
- 헤더/사이드/메인 뼈대, 대시보드 → Grid
- 한 칸이 여러 열·행 먹어야 하면 → Grid (
span,grid-area, 라인)
조합: 바깥은 Grid, 카드 안쪽 정렬은 Flex. 레이어 나누면 CSS 읽기 쉬워진다.
컨테이너: display: grid, grid-template-*
display: grid면 직접 자식이 그리드 아이템. 용어는 ASCII로 보면 빠름.
1 2 3 4 ← 열 라인
1 ┌─────┬─────┬─────┐
│ 1 │ 2 │ 3 │
2 ├─────┼─────┼─────┤
│ 4 │ 5 │ 6 │
3 └─────┴─────┴─────┘
↑ 행 라인
- 3열 = 열 라인 4개 — “전체 너비”는
grid-column: 1 / -1같은 식 min-width: auto때문에 안 줄어드는 자식이 있으면, 실무에선min-width: 0같이 같이 쓰는 경우 많다
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
grid-template-rows: 100px 100px;
gap: 20px;
}
grid-template-areas — 말로는 “ASCII 덩어리”
.app {
display: grid;
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: 80px 1fr 1fr 60px;
grid-template-areas:
"header header header"
"sidebar main main"
"sidebar main main"
"footer footer footer";
min-height: 100vh;
gap: 10px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
같은 이름 셀은 직사각형이어야 한다—꼬이면 areas가 통째로 invalid.
라인·fr·gap·repeat·minmax·auto-fit
라인 번호 grid-column: 1 / 4 = 1번~4번 열 라인 사이 = 3칸. -1은 마지막 라인.
gap은 트랙 사이만. fr은 고정+gap 뺀 남는 공간 비율—퍼센트+갭이랑 싸울 때 fr이 덜 꼬이는 경우가 많다.
.page {
display: grid;
grid-template-columns: 200px 1fr 2fr;
}
반응형 한 방은 흔히 이거:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
auto-fill은 빈 열 슬롯이 남을 수 있고, auto-fit은 빈 열을 접어서 남는 칸이 늘어난다. “카드 꽉 채우기”는 보통 auto-fit부터 써 본다.
auto-fill: [1][2][3][ ][ ] … 빈 트랙 남을 수 있음
auto-fit: [ 1 ][ 2 ][ 3 ] … 접힘, 셀 확장
아이템: span, place-self, 정렬
.card-wide {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.feature {
grid-column: span 2;
}
place-items: 셀 안 정렬(컨테이너)place-content: 그리드 덩어리 전체가 작을 때 남는 여백(컨테이너에 높이/고정 트랙 있을 때)
grid-auto-flow: dense는 빈칸 메울 수 있지만 시각 순서 vs 포커스 순서 괴리 날 수 있어서, 폼·리스트는 신중히.
실전: 대시보드 뼈대만
<div class="dashboard">
<header class="dashboard__header">헤더</header>
<aside class="dashboard__side">사이드</aside>
<div class="dashboard__stats">…KPI 3칸…</div>
<section class="dashboard__chart">차트</section>
</div>
.dashboard {
min-height: 100vh;
display: grid;
gap: 20px;
padding: 20px;
grid-template-columns: 240px 1fr 1fr;
grid-template-rows: 72px 140px 1fr;
grid-template-areas:
"head head head"
"side stat stat"
"side chart chart";
}
.dashboard__header { grid-area: head; }
.dashboard__side { grid-area: side; }
.dashboard__stats { grid-area: stat; display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.dashboard__chart { grid-area: chart; }
좁아지면 @media에서 grid-template-areas만 세로로 갈아끼우면 된다. Holy Grail·갤러리 span 트릭·카드 auto-fit은 같은 원리라 여기서 굳이 길게 안 늘렸다. 더 필요하면 시리즈 다른 글·심화 글 봐.
Grid + Flex (이건 진짜 자주 씀)
.page { display: grid; grid-template-columns: 220px 1fr; }
.toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
뼈대 2D = Grid, 한 줄·한 축 = Flex — 고집할 주제가 아니다. 다만 “전체를 Flex만으로 2D 흉내” 내는 쪽이 더 빨리 지저분해지는 경향은 있다. Grid가 답인 자리는 Grid 쓰자.
브라우저·트러블 (한 덩어리로)
모던 브라우저는 Grid Level 1 잘 쓴다. IE11 레거시면 -ms-·폴리필 이야기가 따로—2026 신규면 보통 대상 밖. subgrid는 Can I use 보고.
자주 터지는 것들을 표 대신:
- 넘침 →
min-width: 0/overflow/word-break fr이상 → 콘텐츠가 트랙 최소를 밀어 올림 —minmax(0, 1fr)등 상황마다areas깨짐 → 같은 이름이 직사각형 아님 — ASCII 다시 그려align-content안 먹음 → 행 합이 이미 뷰포트 꽉 참 —min-height/height·행 정의 점검
DevTools → Layout → Grid 오버레이는 필수다. Grid 디버깅으로 하루 쓴 사람은 다 동의함.
display: grid 기본 3×2 느낌 예시
<div class="grid">
<div class="item i1">1</div>
<div class="item i2">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 100px);
gap: 10px;
}
.i1 { grid-column: 1 / 3; }
.i2 { grid-column: 3 / 5; grid-row: 1 / 3; }
정리
- Grid = 2D, Flex = 1D — 페이지 격자는 Grid 먼저 생각.
grid-template-*,gap,fr/minmax/auto-fit,areas,span,1 / -1.min-width: 0,areas직사각형,dense+접근성은 머리에 두기.- 반말로 말하자면: 막힐 땐 DevTools grid 선 켜. 그게 젤 빠름.
속성 위치만 빠르게: 컨테이너 쪽은 template, gap, place-items / place-content, grid-auto-* — 아이템은 grid-column·row·grid-area, place-self. 표로 안 깔고, 위에서 이미 썼다.
다음에 읽을 글
관련 글
- CSS 박스 모델 | Margin, Padding, Border 완벽 정리
- CSS Flexbox | 플렉스박스 레이아웃 완벽 가이드
- HTML/CSS 시작하기 | 웹 개발 첫걸음
- CSS 기초 | 선택자, 속성, 색상, 폰트
- 반응형 웹 디자인 | 미디어 쿼리와 모바일 최적화
같이 보면 좋은 내부 글(심화·교차)
키워드: CSS, Grid, 레이아웃, 그리드, grid-template-areas, fr, minmax, auto-fit
자주 묻는 질문 (보충)
Q. justify-items와 justify-content의 차이는?
A. …-items는 각 셀 안의 아이템, …-content는 트랙 전체가 작을 때 남는 여백.
Q. grid와 inline-grid는?
A. inline-grid는 인라인 흐름에 격자 끼워 넣을 때. 기본은 grid 쪽이 많다.
Q. Grid만으로 모든 걸?
A. 아니다. 1차원 정렬·툴바는 Flex가 단순한 경우 많다. 대신 “2D를 Flex로만” 억지로 만들지 말자.
배포 전엔 커밋·푸시 후 npm run deploy 같은 프로젝트 스크립트 쓰는 게 안전하다.