CSS Grid | 그리드 레이아웃 완벽 가이드
이 글의 핵심
CSS Grid에 대한 실전 가이드입니다. 그리드 레이아웃 완벽 가이드 등을 예제와 함께 상세히 설명합니다.
들어가며
”2차원 레이아웃의 완성, Grid”
CSS Grid는 행과 열을 한 번에 정의해, 카드·대시보드처럼 격자가 필요한 화면에 맞습니다. Flexbox가 한 방향(가로 또는 세로)에 강하다면, Grid는 표처럼 2차원을 잡을 때 자주 씁니다.
전통적인 방법의 문제:
/* float + clearfix (구식) */
.col-4 { float: left; width: 33.33%; }
.row::after { content: ""; display: table; clear: both; }
Grid로 해결:
/* 간단하고 강력 */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
Grid의 장점:
- ✅ 2차원 제어: 행과 열을 동시에 관리
- ✅ 명시적 배치: 정확한 위치 지정
- ✅ 반응형:
auto-fit,minmax로 자동 대응 - ✅ 간격 관리:
gap으로 간단하게 - ✅ 복잡한 레이아웃: 성배 레이아웃도 쉽게
1. Grid 기본 개념
컨테이너와 아이템
<div class="container"> <!-- Grid Container -->
<div class="item">1</div> <!-- Grid Item -->
<div class="item">2</div>
<div class="item">3</div>
</div>
.container {
display: grid;
/* 3개 열 (각 200px) */
grid-template-columns: 200px 200px 200px;
/* 2개 행 (각 100px) */
grid-template-rows: 100px 100px;
/* 간격 */
gap: 20px;
}
Grid 용어
┌─────────────────────────────────┐
│ Grid Line (그리드 라인) │
│ ↓ │
│ 1 2 3 4 │
│ ┌─────┬─────┬─────┐ ← Grid Track (트랙)
│1 │ │ │ │ │
│ │ 1 │ 2 │ 3 │ ← Grid Cell (셀)
│2 ├─────┼─────┼─────┤ │
│ │ │ │ │ │
│ │ 4 │ 5 │ 6 │ │
│3 └─────┴─────┴─────┘ │
│ ↑ │
│ Grid Area (영역) │
└─────────────────────────────────┘
2. Grid Template Columns/Rows
열 정의 (Columns)
Grid의 열(column)을 정의하는 다양한 방법입니다:
.container {
display: grid;
/* 1. 고정 크기: 픽셀 단위 */
grid-template-columns: 200px 300px 200px;
/* 3개의 열: 200px, 300px, 200px */
/* 총 너비: 700px (고정) */
/* 2. fr 단위 (fraction, 비율) */
grid-template-columns: 1fr 2fr 1fr;
/* 남은 공간을 1:2:1 비율로 분배 */
/* 예: 컨테이너 800px → 200px, 400px, 200px */
/* fr은 고정 크기를 제외한 나머지 공간을 나눔 */
/* 3. repeat() 함수: 반복 패턴 */
grid-template-columns: repeat(3, 1fr);
/* repeat(횟수, 패턴) */
/* 1fr 1fr 1fr과 동일 (3개 균등 분할) */
grid-template-columns: repeat(2, 100px 200px);
/* 100px 200px 100px 200px (패턴 반복) */
/* 4. auto-fill: 가능한 많은 열 생성 (빈 트랙 유지) */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* minmax(최소, 최대): 열 크기 범위 지정 */
/* 200px 이상, 남은 공간은 균등 분배 */
/* 컨테이너 크기에 따라 열 개수 자동 조정 */
/* 예: 1000px → 4개 열 (각 250px) */
/* 예: 500px → 2개 열 (각 250px) */
/* 5. auto-fit: 빈 트랙 제거하고 확장 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* auto-fill과 유사하지만 빈 트랙을 제거 */
/* 아이템이 적으면 남은 공간을 채움 */
/* 6. 혼합 사용 */
grid-template-columns: 200px 1fr 2fr;
/* 첫 열: 200px 고정 */
/* 나머지 공간을 1:2 비율로 분배 */
/* 예: 컨테이너 1000px → 200px, 267px, 533px */
/* 7. minmax(): 최소/최대 크기 지정 */
grid-template-columns: minmax(200px, 1fr) 1fr;
/* 첫 열: 최소 200px, 최대 1fr */
/* 컨테이너가 작아져도 200px 미만으로 줄어들지 않음 */
}
실전 예시: 반응형 그리드:
.product-grid {
display: grid;
/* 최소 250px, 최대 1fr (균등 분배) */
/* 화면 크기에 따라 열 개수 자동 조정 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
/* 결과:
- 1920px 화면: 7개 열
- 1280px 화면: 5개 열
- 768px 화면: 3개 열
- 375px 화면: 1개 열
미디어 쿼리 없이 자동 반응형!
*/
fr vs % 차이:
/* % : 컨테이너 전체 크기 기준 */
grid-template-columns: 25% 50% 25%;
/* gap을 추가하면 100%를 초과하여 줄바꿈 발생 */
/* fr : gap을 제외한 남은 공간 기준 */
grid-template-columns: 1fr 2fr 1fr;
/* gap을 추가해도 자동으로 조정됨 (권장) */
auto-fill vs auto-fit
/* auto-fill: 빈 트랙 유지 */
.grid-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
/* auto-fit: 빈 트랙 제거 */
.grid-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
차이점:
auto-fill (3개 아이템, 공간 충분)
[1][2][3][ ][ ] ← 빈 트랙 유지
auto-fit (3개 아이템, 공간 충분)
[ 1 ][ 2 ][ 3 ] ← 빈 트랙 제거, 아이템 확장
행 정의 (Rows)
.container {
display: grid;
/* 고정 높이 */
grid-template-rows: 100px 200px;
/* 자동 높이 (내용 기반) */
grid-template-rows: auto auto;
/* 최소/최대 */
grid-template-rows: minmax(100px, auto);
/* 반복 */
grid-template-rows: repeat(3, 150px);
}
실전 예제
<style>
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
padding: 20px;
}
.product {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.product img {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 5px;
}
.product h3 {
margin: 15px 0 10px 0;
}
.product .price {
font-size: 1.5rem;
color: #3498db;
font-weight: bold;
}
</style>
<div class="product-grid">
<div class="product">
<img src="product1.jpg" alt="상품 1">
<h3>상품 1</h3>
<p>상품 설명...</p>
<div class="price">29,000원</div>
</div>
<!-- 더 많은 상품... -->
</div>
3. Gap (간격)
간격 설정
.container {
display: grid;
/* 행과 열 모두 20px */
gap: 20px;
/* 행 20px, 열 10px */
gap: 20px 10px;
/* 개별 지정 */
row-gap: 20px;
column-gap: 10px;
}
gap vs margin 비교:
/* ✅ gap 사용 (권장) */
.container {
display: grid;
gap: 20px; /* 간단 */
}
/* ❌ margin 사용 (구식) */
.item {
margin: 10px; /* 복잡 */
}
.container {
margin: -10px; /* 음수 마진으로 보정 */
}
4. Grid Item 배치
Grid Column/Row (라인 번호)
.item {
/* 열: 1번 라인부터 3번 라인까지 */
grid-column: 1 / 3;
/* 열: 1번 라인부터 2칸 */
grid-column: 1 / span 2;
/* 열: 시작 / 끝 */
grid-column-start: 1;
grid-column-end: 3;
/* 행: 1번 라인부터 3번 라인까지 */
grid-row: 1 / 3;
/* 행: 1번 라인부터 2칸 */
grid-row: 1 / span 2;
}
예제:
<style>
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
padding: 10px;
}
.item {
background: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
}
.item-1 {
grid-column: 1 / 3; /* 2칸 */
grid-row: 1 / 2;
background: #e74c3c;
}
.item-2 {
grid-column: 3 / 5; /* 2칸 */
grid-row: 1 / 3; /* 2행 */
background: #2ecc71;
}
</style>
<div class="grid">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
Grid Area (영역 이름)
이름으로 배치하는 직관적인 방법입니다.
.container {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"sidebar main main"
"footer footer footer";
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: 80px 1fr 1fr 60px;
gap: 10px;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
반응형 레이아웃:
/* 데스크톱 */
.container {
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
}
/* 모바일 */
@media (max-width: 768px) {
.container {
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
grid-template-columns: 1fr;
}
}
Grid Template (축약)
.container {
display: grid;
/* grid-template-rows / grid-template-columns */
grid-template: 100px 200px / 1fr 2fr;
/* grid-template-areas와 함께 */
grid-template:
"header header" 80px
"sidebar main" 1fr
"footer footer" 60px
/ 200px 1fr;
}
5. 정렬 (Alignment)
Justify Items (수평 정렬)
셀 내부에서 아이템의 수평 정렬을 제어합니다.
.container {
display: grid;
justify-items: start; /* 왼쪽 */
justify-items: end; /* 오른쪽 */
justify-items: center; /* 중앙 */
justify-items: stretch; /* 늘림 (기본값) */
}
Align Items (수직 정렬)
셀 내부에서 아이템의 수직 정렬을 제어합니다.
.container {
display: grid;
align-items: start; /* 위 */
align-items: end; /* 아래 */
align-items: center; /* 중앙 */
align-items: stretch; /* 늘림 (기본값) */
}
Place Items (축약)
.container {
/* align-items / justify-items */
place-items: center center;
place-items: center; /* 둘 다 center */
}
Justify Content (그리드 전체 수평 정렬)
컨테이너 내부에서 그리드 전체의 수평 정렬을 제어합니다.
.container {
display: grid;
grid-template-columns: repeat(3, 200px); /* 고정 크기 */
justify-content: start; /* 왼쪽 */
justify-content: end; /* 오른쪽 */
justify-content: center; /* 중앙 */
justify-content: space-between; /* 양끝 */
justify-content: space-around; /* 주위 균등 */
justify-content: space-evenly; /* 완전 균등 */
}
Align Content (그리드 전체 수직 정렬)
.container {
display: grid;
height: 600px;
align-content: start;
align-content: end;
align-content: center;
align-content: space-between;
align-content: space-around;
align-content: stretch; /* 기본값 */
}
개별 아이템 정렬
.item {
/* 개별 수평 정렬 */
justify-self: center;
/* 개별 수직 정렬 */
align-self: center;
/* 축약 */
place-self: center;
}
6. 명명된 라인 (Named Lines)
라인에 이름 지정
.container {
display: grid;
grid-template-columns:
[sidebar-start] 200px
[sidebar-end main-start] 1fr
[main-end];
grid-template-rows:
[header-start] 80px
[header-end content-start] 1fr
[content-end footer-start] 60px
[footer-end];
}
.header {
grid-column: sidebar-start / main-end;
grid-row: header-start / header-end;
}
.sidebar {
grid-column: sidebar-start / sidebar-end;
grid-row: content-start / content-end;
}
.main {
grid-column: main-start / main-end;
grid-row: content-start / content-end;
}
7. Auto Placement (자동 배치)
Grid Auto Flow
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* 행 우선 (기본값) */
grid-auto-flow: row;
/* 열 우선 */
grid-auto-flow: column;
/* 빈 공간 채우기 */
grid-auto-flow: dense;
}
Grid Auto Columns/Rows
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* 자동 생성되는 행의 크기 */
grid-auto-rows: 100px;
/* 최소/최대 */
grid-auto-rows: minmax(100px, auto);
}
예제:
<style>
.auto-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
gap: 10px;
padding: 10px;
}
.item {
background: #3498db;
color: white;
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
}
/* 일부 아이템만 크기 지정 */
.item-large {
grid-column: span 2; /* 2칸 */
background: #e74c3c;
}
</style>
<div class="auto-grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item item-large">4 (2칸)</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>
8. 실전 예제
예제 1: 대시보드 레이아웃
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>대시보드</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background: #f5f6fa;
}
.dashboard {
display: grid;
grid-template-areas:
"header header header header"
"sidebar stats stats stats"
"sidebar chart chart chart"
"sidebar recent recent activity";
grid-template-columns: 250px 1fr 1fr 1fr;
grid-template-rows: 80px 150px 300px 200px;
gap: 20px;
padding: 20px;
min-height: 100vh;
}
.header {
grid-area: header;
background: white;
border-radius: 10px;
padding: 0 30px;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.header h1 {
color: #2c3e50;
}
.sidebar {
grid-area: sidebar;
background: #2c3e50;
color: white;
border-radius: 10px;
padding: 20px;
}
.sidebar ul {
list-style: none;
margin-top: 20px;
}
.sidebar li {
padding: 10px;
margin-bottom: 5px;
border-radius: 5px;
cursor: pointer;
}
.sidebar li:hover {
background: rgba(255,255,255,0.1);
}
.stats {
grid-area: stats;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.stat-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.stat-card h3 {
color: #7f8c8d;
font-size: 0.9rem;
margin-bottom: 10px;
}
.stat-card .value {
font-size: 2rem;
font-weight: bold;
color: #2c3e50;
}
.chart {
grid-area: chart;
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.recent {
grid-area: recent;
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.activity {
grid-area: activity;
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
/* 반응형 */
@media (max-width: 1024px) {
.dashboard {
grid-template-areas:
"header"
"stats"
"chart"
"recent"
"activity"
"sidebar";
grid-template-columns: 1fr;
grid-template-rows: auto;
}
.stats {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="dashboard">
<header class="header">
<h1>대시보드</h1>
<div>사용자 메뉴</div>
</header>
<aside class="sidebar">
<h2>메뉴</h2>
<ul>
<li>대시보드</li>
<li>통계</li>
<li>설정</li>
</ul>
</aside>
<div class="stats">
<div class="stat-card">
<h3>총 방문자</h3>
<div class="value">12,345</div>
</div>
<div class="stat-card">
<h3>신규 가입</h3>
<div class="value">234</div>
</div>
<div class="stat-card">
<h3>매출</h3>
<div class="value">$5,678</div>
</div>
</div>
<section class="chart">
<h2>차트</h2>
<p>차트 영역...</p>
</section>
<section class="recent">
<h2>최근 활동</h2>
<p>활동 목록...</p>
</section>
<section class="activity">
<h2>알림</h2>
<p>알림 목록...</p>
</section>
</div>
</body>
</html>
예제 2: 갤러리 (Masonry 스타일)
<style>
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 10px; /* 작은 단위 */
gap: 10px;
padding: 10px;
}
.gallery-item {
background: #ddd;
border-radius: 5px;
overflow: hidden;
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* 다양한 크기 */
.gallery-item:nth-child(1) {
grid-row: span 20; /* 200px */
}
.gallery-item:nth-child(2) {
grid-row: span 30; /* 300px */
}
.gallery-item:nth-child(3) {
grid-row: span 25; /* 250px */
}
.gallery-item:nth-child(4) {
grid-column: span 2; /* 2칸 */
grid-row: span 40; /* 400px */
}
</style>
<div class="gallery">
<div class="gallery-item">
<img src="image1.jpg" alt="이미지 1">
</div>
<div class="gallery-item">
<img src="image2.jpg" alt="이미지 2">
</div>
<div class="gallery-item">
<img src="image3.jpg" alt="이미지 3">
</div>
<div class="gallery-item">
<img src="image4.jpg" alt="이미지 4">
</div>
<div class="gallery-item">
<img src="image5.jpg" alt="이미지 5">
</div>
<div class="gallery-item">
<img src="image6.jpg" alt="이미지 6">
</div>
</div>
예제 3: 카드 레이아웃
<style>
.card-layout {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
}
.card {
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: transform 0.3s;
}
.card:hover {
transform: translateY(-5px);
}
.card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.card-content {
padding: 20px;
}
.card h3 {
margin: 0 0 10px 0;
color: #2c3e50;
}
.card p {
margin: 0 0 15px 0;
color: #7f8c8d;
line-height: 1.6;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
border-top: 1px solid #ecf0f1;
}
/* 특별한 카드 (2칸) */
.card-featured {
grid-column: span 2;
}
</style>
<div class="card-layout">
<div class="card card-featured">
<img src="featured.jpg" alt="특집">
<div class="card-content">
<h3>특집 기사</h3>
<p>중요한 내용...</p>
</div>
<div class="card-footer">
<span>2026-03-29</span>
<button>더보기</button>
</div>
</div>
<div class="card">
<img src="article1.jpg" alt="기사 1">
<div class="card-content">
<h3>기사 1</h3>
<p>내용...</p>
</div>
</div>
<div class="card">
<img src="article2.jpg" alt="기사 2">
<div class="card-content">
<h3>기사 2</h3>
<p>내용...</p>
</div>
</div>
</div>
9. 자주 발생하는 문제
1. 아이템이 넘침
문제:
.item {
/* 내용이 셀을 넘어감 */
}
해결:
.item {
overflow: hidden; /* 숨김 */
/* 또는 */
overflow: auto; /* 스크롤 */
}
2. fr 단위와 고정 크기 혼용
문제:
/* 의도: 사이드바 200px, 나머지 균등 */
.container {
grid-template-columns: 200px 1fr 1fr;
/* 실제: 200px + (남은공간/2) + (남은공간/2) ✅ */
}
주의: fr은 남은 공간을 분배합니다.
/* 전체를 3:1:1로 나누려면 */
.container {
grid-template-columns: 3fr 1fr 1fr;
}
3. 최소 크기 문제
문제: 아이템이 줄어들지 않음
.item {
/* 기본적으로 min-width: auto */
}
해결:
.item {
min-width: 0; /* 최소 크기 제한 해제 */
overflow: hidden;
}
4. 그리드 라인 번호 혼동
3개 열 = 4개 라인
1 2 3 4
┌─────┬─────┬─────┐
│ 1 │ 2 │ 3 │
└─────┴─────┴─────┘
grid-column: 1 / 4 ← 전체 (1~4번 라인)
grid-column: 1 / 3 ← 1~2번 셀 (1~3번 라인)
5. Grid Area 오타
문제:
.container {
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.sidebar { grid-area: sidbar; } /* 오타! */
해결: 이름을 정확히 일치시킵니다.
10. Flexbox vs Grid 비교
언제 무엇을 사용할까?
| 기준 | Flexbox | Grid |
|---|---|---|
| 차원 | 1차원 (가로 또는 세로) | 2차원 (가로 + 세로) |
| 용도 | 네비게이션, 버튼 그룹, 단순 나열 | 페이지 레이아웃, 복잡한 그리드 |
| 정렬 | 주축/교차축 | 행/열 |
| 아이템 크기 | 내용 기반 + flex | 명시적 크기 지정 |
| 간격 | gap (또는 margin) | gap |
| 배치 | 순서대로 | 명시적 위치 지정 |
| 반응형 | 방향 전환 | 영역 재배치 |
선택 가이드
✅ Flexbox 사용:
- 네비게이션 바
- 버튼 그룹
- 카드를 가로로 나열
- 중앙 정렬
- 폼 필드 정렬
- 한 방향으로만 배치
✅ Grid 사용:
- 전체 페이지 레이아웃
- 갤러리 (행과 열)
- 대시보드
- 복잡한 그리드
- 정확한 위치 지정
- 행과 열을 동시에 제어
✅ 함께 사용:
- Grid로 전체 레이아웃
- Flexbox로 세부 정렬
예제:
/* Grid로 전체 레이아웃 */
.container {
display: grid;
grid-template-columns: 250px 1fr;
}
/* Flexbox로 네비게이션 */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
}
11. 실전 팁
1. 디버깅
.container {
/* 그리드 라인 확인 */
border: 2px solid red;
}
.item {
border: 1px solid blue;
}
Chrome DevTools:
- 요소 선택
- Styles 패널에서 Grid 아이콘 클릭
- 그리드 라인과 영역 시각화
2. 반응형 패턴
/* 모바일: 1열 */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
/* 태블릿: 2열 */
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* 데스크톱: 자동 채우기 */
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
}
3. 자주 사용하는 패턴
/* 균등 분배 */
grid-template-columns: repeat(3, 1fr);
/* 자동 반응형 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
/* 고정 사이드바 */
grid-template-columns: 250px 1fr;
/* 중앙 정렬 */
place-items: center;
/* 전체 영역 */
grid-column: 1 / -1; /* -1은 마지막 라인 */
4. 성능 최적화
/* ✅ 좋음: 명시적 크기 */
.grid {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px;
}
/* ❌ 나쁨: 크기 미지정 (레이아웃 계산 복잡) */
.grid {
display: grid;
/* 크기 없음 */
}
12. 브라우저 지원
지원 현황
| 브라우저 | 버전 |
|---|---|
| Chrome | 57+ |
| Firefox | 52+ |
| Safari | 10.1+ |
| Edge | 16+ |
| IE | 11 (부분, -ms- 프리픽스) |
IE 11 지원
.container {
display: -ms-grid; /* IE 11 */
display: grid; /* 표준 */
-ms-grid-columns: 1fr 20px 1fr 20px 1fr; /* gap 포함 */
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.item:nth-child(1) {
-ms-grid-column: 1;
-ms-grid-row: 1;
}
13. grid-template-columns / rows 실무 체크리스트
- 열(
grid-template-columns): 가로 트랙 개수와 너비를 정의합니다. **행(grid-template-rows)**은 대부분auto·minmax·1fr로 두고, 필요한 행만 명시해도 됩니다. - 고정 + 유연 패턴:
grid-template-columns: 240px 1fr 1fr— 사이드바 고정, 오른쪽은 비율 분할. - 전부 유연:
repeat(12, 1fr)또는repeat(auto-fit, minmax(260px, 1fr))— 카드·대시보드에 자주 씁니다.
14. fr, minmax(), auto-fit vs auto-fill — 선택 가이드
fr: 고정 길이와gap을 제외한 남은 공간을 비율로 나눕니다. 퍼센트보다 갭과 함께 쓰기 쉽습니다.minmax(최소, 최대): 트랙이 너무 작아지지 않게 하한을 걸 때 필수입니다. 카드 그리드에서minmax(280px, 1fr)는 매우 흔한 패턴입니다.auto-fill: “들어갈 수 있는 만큼 열을 만들고”, 아이템이 없어도 빈 트랙이 남을 수 있습니다. 배경 격자처럼 열 슬롯을 유지할 때 유리합니다.auto-fit: 빈 열을 접어서 남은 아이템이 늘어나게 합니다. 카드가 적을 때 한 줄을 꽉 채우는 느낌을 낼 때 많이 씁니다.
실무 기본값: 반응형 카드/제품 목록은 repeat(auto-fit, minmax(…, 1fr)) 로 시작하고, “빈 칸까지 항상 보이게” 같은 요구가 있으면 auto-fill을 검토합니다.
15. grid-area로 레이아웃 정의하기
이름 기반(권장 — 이미 4절에서 다룸):
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"head head"
"side main"
"foot foot";
min-height: 100vh;
}
.header { grid-area: head; }
.sidebar { grid-area: side; }
.main { grid-area: main; }
.footer { grid-area: foot; }
라인 번호 기반(세밀한 제어):
.hero {
grid-column: 1 / -1; /* 첫 열부터 마지막 열까지 */
grid-row: 1 / 2;
}
grid-area의 숫자 형태 grid-row-start / grid-column-start / grid-row-end / grid-column-end는 짧게 쓸 수 있지만, 팀 규칙에 따라 **이름 기반 grid-template-areas**와 혼용하지 않도록 정하는 경우가 많습니다.
16. Flexbox vs Grid — 선택 기준(요약)
| 상황 | 추천 |
|---|---|
| 한 방향 정렬·분배(로고+메뉴, 버튼 줄, 폼 한 줄) | Flexbox |
| 행·열 동시에 맞춘 페이지 뼈대, 대시보드, 격자 갤러리 | Grid |
| 카드가 줄바꿈되며 열 개수만 바뀌면 됨 | Grid auto-fit/minmax 또는 Flex wrap+basis |
| 특정 셀이 여러 칸을 차지 | Grid가 유리(span, grid-area) |
함께 쓰기: 바깥은 Grid로 영역을 나누고, 각 셀 안은 Flex로 정렬하는 조합이 매우 흔합니다.
정리
핵심 요약
- display: grid: Grid 활성화
- grid-template-columns: 열 정의
- grid-template-rows: 행 정의
- gap: 간격
- grid-area: 영역 이름으로 배치
- fr 단위: 비율로 공간 분배
- repeat(): 반복 패턴
- minmax(): 최소/최대 크기
- auto-fill/auto-fit: 자동 반응형
Grid 속성 치트시트
| 속성 | 대상 | 설명 |
|---|---|---|
display: grid | Container | Grid 활성화 |
grid-template-columns | Container | 열 정의 |
grid-template-rows | Container | 행 정의 |
grid-template-areas | Container | 영역 정의 |
gap | Container | 간격 |
justify-items | Container | 셀 내 수평 정렬 |
align-items | Container | 셀 내 수직 정렬 |
justify-content | Container | 그리드 전체 수평 정렬 |
align-content | Container | 그리드 전체 수직 정렬 |
grid-auto-flow | Container | 자동 배치 방향 |
grid-auto-rows | Container | 자동 행 크기 |
grid-column | Item | 열 위치 |
grid-row | Item | 행 위치 |
grid-area | Item | 영역 이름 |
justify-self | Item | 개별 수평 정렬 |
align-self | Item | 개별 수직 정렬 |
실전 팁
- repeat(): 반복 패턴 간단하게
- fr 단위: 비율 기반 레이아웃
- minmax(): 최소/최대 크기 제한
- auto-fill: 공간에 맞춰 자동 채우기
- grid-template-areas: 직관적인 레이아웃 정의
- gap: margin보다 간단
- span: 여러 칸 차지
- -1: 마지막 라인 참조
- Chrome DevTools: Grid 디버깅 도구 활용
- Flexbox와 조합: Grid로 전체, Flexbox로 세부
다음 단계
- 반응형 웹 디자인
- CSS 애니메이션
- JavaScript와 함께 사용하기
관련 글
- CSS 박스 모델 | Margin, Padding, Border 완벽 정리
- CSS Flexbox | 플렉스박스 레이아웃 완벽 가이드
- HTML/CSS 시작하기 | 웹 개발 첫걸음
- CSS 기초 | 선택자, 속성, 색상, 폰트
- 반응형 웹 디자인 | 미디어 쿼리와 모바일 최적화