CSS Grid 완전정복
2차원 레이아웃의 모든 것 — 개념부터 실습까지
display: grid
repeat() / fr
minmax()
auto-fill / auto-fit
grid-area
grid-auto-flow
CHAPTER 01
display: grid
부모 요소에
display: grid를 선언하면 자식 요소들이 그리드 아이템이 됩니다. Flexbox가 1차원(행 또는 열)이라면, Grid는 행과 열을 동시에 제어하는 2차원 레이아웃이에요.코드
.container {
display: grid; /* 그리드 활성화 */
grid-template-columns: repeat(3, 1fr);
}
display: grid; /* 그리드 활성화 */
grid-template-columns: repeat(3, 1fr);
}
라이브 프리뷰
LIVE PREVIEW
아이템 1
아이템 2
아이템 3
아이템 4
아이템 5
아이템 6
💡 Flexbox vs Grid — Flexbox는 가로 또는 세로 한 방향, Grid는 가로 + 세로 동시 제어. 레이아웃 전체 구조는 Grid, 내부 정렬은 Flex가 일반적이에요.
CHAPTER 02
repeat() + fr 단위
repeat(횟수, 크기)로 같은 컬럼을 반복하고, fr은 남은 공간의 비율을 나타냅니다.코드
/* repeat(반복횟수, 크기) */
grid-template-columns: repeat(3, 1fr);
/* = 1fr 1fr 1fr (3번 반복) */
/* fr = 남은 공간의 비율 */
grid-template-columns: 2fr 1fr 1fr; /* 2:1:1 비율 */
grid-template-columns: repeat(3, 1fr);
/* = 1fr 1fr 1fr (3번 반복) */
/* fr = 남은 공간의 비율 */
grid-template-columns: 2fr 1fr 1fr; /* 2:1:1 비율 */
라이브 프리뷰 — 컬럼 수 조절
LIVE PREVIEW
1
2
3
4
5
6
컬럼 수
3
fr 비율 비교
1fr 1fr 1fr (균등)
1fr
1fr
1fr
2fr 1fr 1fr (2:1:1)
2fr
1fr
1fr
💡
repeat(3, 1fr)은 1fr 1fr 1fr과 완전히 동일해요. repeat(2, 2fr 1fr)처럼 패턴 반복도 가능해요!CHAPTER 03
minmax()
minmax(최솟값, 최댓값)으로 컬럼 너비에 범위를 지정합니다. 최솟값보다 작아지지 않고, 최댓값보다 커지지 않아요.코드
grid-template-columns: repeat(3, minmax(80px, 1fr));
/* 최소 80px, 최대 1fr(남은 공간) */
/* 자주 쓰는 패턴 */
grid-template-columns: repeat(3, minmax(150px, 1fr)); /* 반응형 카드 */
grid-template-columns: repeat(3, minmax(0, 1fr)); /* = 1fr (안전) */
/* 최소 80px, 최대 1fr(남은 공간) */
/* 자주 쓰는 패턴 */
grid-template-columns: repeat(3, minmax(150px, 1fr)); /* 반응형 카드 */
grid-template-columns: repeat(3, minmax(0, 1fr)); /* = 1fr (안전) */
라이브 프리뷰 — 컨테이너 너비 + 최솟값 동시 조절
LIVE PREVIEW — 컨테이너를 줄이면 최솟값이 언제 발동하는지 보여요
min: 80px
긴 텍스트
짧음
컨테이너 100% — 칸당 여유 충분 → 1fr 균등 분배
최솟값 (min)
80px
컨테이너 너비
100%
💡 min에는 px, max에는 fr을 조합하는 게 가장 많이 쓰이는 패턴이에요.
min-content, max-content도 사용 가능해요.CHAPTER 04
auto-fill vs auto-fit
컨테이너 너비에 따라 컬럼 수를 자동으로 결정해요. 차이는 아이템이 트랙보다 적을 때 빈 트랙 처리 방식에 있어요.
코드
/* auto-fill: 빈 트랙 유지 */
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
/* auto-fit: 빈 트랙 0px로 접음 → 아이템이 늘어남 */
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
/* auto-fit: 빈 트랙 0px로 접음 → 아이템이 늘어남 */
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
라이브 프리뷰 — 아이템 수 조절해서 비교
auto-fill 빈 트랙 유지
A
B
C
auto-fit 빈 트랙 접힘
A
B
C
아이템 수
3
💡 실무에서는 auto-fit이 더 많이 쓰여요. 아이템이 적어도 전체 너비를 꽉 채우니까요. 공식:
repeat(auto-fit, minmax(200px, 1fr))CHAPTER 05
grid-column / grid-row
그리드 라인 번호로 아이템이 차지할 영역을 지정해요. 라인 번호는 칸 번호가 아니라 선의 번호예요.
코드
.item {
grid-column: 1 / 3; /* 열: 1번 라인 ~ 3번 라인 = 2칸 */
grid-row: 1 / 3; /* 행: 1번 라인 ~ 3번 라인 = 2칸 */
}
/* span 문법 — 같은 결과 */
grid-column: 1 / span 2; /* 1번 라인에서 2칸 */
grid-column: 1 / -1; /* 전체 너비 */
grid-column: 1 / 3; /* 열: 1번 라인 ~ 3번 라인 = 2칸 */
grid-row: 1 / 3; /* 행: 1번 라인 ~ 3번 라인 = 2칸 */
}
/* span 문법 — 같은 결과 */
grid-column: 1 / span 2; /* 1번 라인에서 2칸 */
grid-column: 1 / -1; /* 전체 너비 */
라이브 프리뷰 — 라인 번호 조절
LIVE PREVIEW — 파란 아이템의 영역을 바꿔보세요
★ item
B
C
D
E
column-start
1
column-end
3
row-start
1
row-end
3
⚠️ 라인 번호 ≠ 칸 번호! 3×3 그리드면 라인이 4개(1~4)예요.
grid-column: 1/3은 2칸, 1/4는 3칸(전체)이에요.CHAPTER 06
grid-template-areas
레이아웃을 문자로 그림처럼 표현해요. 부모가 이름 지도를 그리면 자식이
grid-area로 자기 자리를 찾아가요.코드
.container {
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
". . . a" ← 점(.)은 빈 칸
". . b c"
". d e f"
"g h i .";
}
.item1 { grid-area: a; }
.item2 { grid-area: b; } /* ... */
/* 반응형 — 미디어쿼리에서 areas만 다시 쓰면 됨 */
@media (max-width: 768px) {
.container {
grid-template-columns: repeat(2, 1fr);
grid-template-areas: "a b" "c d" "e f" "g h" "i .";
}
}
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
". . . a" ← 점(.)은 빈 칸
". . b c"
". d e f"
"g h i .";
}
.item1 { grid-area: a; }
.item2 { grid-area: b; } /* ... */
/* 반응형 — 미디어쿼리에서 areas만 다시 쓰면 됨 */
@media (max-width: 768px) {
.container {
grid-template-columns: repeat(2, 1fr);
grid-template-areas: "a b" "c d" "e f" "g h" "i .";
}
}
라이브 프리뷰
LIVE PREVIEW
a
b
c
d
e
f
g
h
i
반응형
💡 핵심: 자식의
grid-area는 그대로, 부모의 grid-template-areas만 바꾸면 레이아웃이 완전히 달라져요. absolute → static처럼 덮어쓰기예요!CHAPTER 07
grid-auto-flow
아이템이 자동 배치될 때 흐르는 방향을 정해요. 기본값은
row(가로)예요.코드
grid-auto-flow: row; /* 기본값 — 가로로 흐름 */
grid-auto-flow: column; /* 세로로 흐름 (grid-template-rows도 필요) */
grid-auto-flow: row dense; /* 빈 칸을 뒤 아이템으로 채움 */
grid-auto-flow: column; /* 세로로 흐름 (grid-template-rows도 필요) */
grid-auto-flow: row dense; /* 빈 칸을 뒤 아이템으로 채움 */
라이브 프리뷰
row (기본) → 1→2→3 / 4→5→6
1
2
3
4
5
6
column → 1↓2 / 3↓4 / 5↓6
1
2
3
4
5
6
dense — 빈 칸 채우기 (크기가 다를 때)
row (빈 칸 유지)
1 (2칸)
2 (2칸)
3 (1칸)
4 (1칸)
5 (1칸)
⚠️ 1번 뒤, 2번 뒤에 빈 칸 — 3,4,5가 다음 행으로 밀림
row dense 빈 칸 채움
1 (2칸)
2 (2칸)
3 (1칸)
4 (1칸)
5 (1칸)
✅ 3번이 1번 뒤 빈 칸으로, 4번이 2번 뒤 빈 칸으로 당겨짐
⚠️
grid-auto-flow: column은 grid-template-rows도 함께 정의해야 의도대로 동작해요. 행이 1개만 있으면 한 줄로 나열돼요!CHAPTER 08
gap / grid-auto-rows
아이템 간 간격과 자동 생성되는 행의 크기를 설정해요.
코드
/* gap: 행간격 열간격 */
gap: 20px; /* 행·열 동시 */
gap: 20px 10px; /* 행 20px, 열 10px */
row-gap: 20px; /* 행만 */
column-gap: 10px; /* 열만 */
/* grid-auto-rows: 명시하지 않은 행의 기본 크기 */
grid-auto-rows: minmax(180px, auto);
/* 최소 180px, 내용 많으면 늘어남 */
gap: 20px; /* 행·열 동시 */
gap: 20px 10px; /* 행 20px, 열 10px */
row-gap: 20px; /* 행만 */
column-gap: 10px; /* 열만 */
/* grid-auto-rows: 명시하지 않은 행의 기본 크기 */
grid-auto-rows: minmax(180px, auto);
/* 최소 180px, 내용 많으면 늘어남 */
라이브 프리뷰 — gap 조절
LIVE PREVIEW
1
2
3
4
5
6
row-gap
16px
column-gap
16px
CHAPTER 09
실습 예제
오늘 배운 Grid 개념을 실제 사이트 레이아웃에 적용해보아요.
NH농협 그룹사 소개 — grid-template-areas + 반응형
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(180px, auto);
grid-template-areas:
". . . a"
". . b c"
". d e f"
"g h i .";
}
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(180px, auto);
grid-template-areas:
". . . a"
". . b c"
". d e f"
"g h i .";
}
LIVE PREVIEW
NH농협리츠운용
NH농협생명
NH투자증권
NH농협손해보험
NH농협은행
NH-Amundi
NH밴처투자
NH저축은행
NH농협캐피탈
파트너 로고 — 행 분리 + calc()
/* 행을 두 개로 분리 */
.row1 { grid-template-columns: repeat(5, 1fr); }
.row2 {
grid-template-columns: repeat(4, 1fr);
padding: 0 calc(100% / 10); /* 반칸씩 들여써서 가운데 정렬 */
}
.row1 { grid-template-columns: repeat(5, 1fr); }
.row2 {
grid-template-columns: repeat(4, 1fr);
padding: 0 calc(100% / 10); /* 반칸씩 들여써서 가운데 정렬 */
}
LIVE PREVIEW
S-OIL
KOREAN AIR
NH투자증권
하나은행
ILDONG
DAOU
단국대학교
Sunmight
혜원의료재단
@hince_official — 불규칙 갤러리 3가지 방법
/* 방법 1: grid-column/row 직접 지정 */
.container { grid-template-columns: 1fr 0.5fr 1fr 0.5fr 1fr; }
.item1, .item4, .item7 { grid-row: 1 / 3; }
.item4 { grid-column: 3 / 4; }
.item7 { grid-column: 5 / 6; }
/* 방법 2: grid-template-areas */
grid-template-areas:
"a b c d e"
"a f c g e";
/* 방법 3: span */
.item1, .item4, .item7 { grid-row: span 2; }
.item4 { grid-column: 3; }
.container { grid-template-columns: 1fr 0.5fr 1fr 0.5fr 1fr; }
.item1, .item4, .item7 { grid-row: 1 / 3; }
.item4 { grid-column: 3 / 4; }
.item7 { grid-column: 5 / 6; }
/* 방법 2: grid-template-areas */
grid-template-areas:
"a b c d e"
"a f c g e";
/* 방법 3: span */
.item1, .item4, .item7 { grid-row: span 2; }
.item4 { grid-column: 3; }
LIVE PREVIEW
01
tall
tall
02
03
04
tall
tall
05
06
07
tall
tall