CSS Grid | 그리드 레이아웃 완벽 가이드

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 비교

언제 무엇을 사용할까?

기준FlexboxGrid
차원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:

  1. 요소 선택
  2. Styles 패널에서 Grid 아이콘 클릭
  3. 그리드 라인과 영역 시각화

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. 브라우저 지원

지원 현황

브라우저버전
Chrome57+
Firefox52+
Safari10.1+
Edge16+
IE11 (부분, -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로 정렬하는 조합이 매우 흔합니다.


정리

핵심 요약

  1. display: grid: Grid 활성화
  2. grid-template-columns: 열 정의
  3. grid-template-rows: 행 정의
  4. gap: 간격
  5. grid-area: 영역 이름으로 배치
  6. fr 단위: 비율로 공간 분배
  7. repeat(): 반복 패턴
  8. minmax(): 최소/최대 크기
  9. auto-fill/auto-fit: 자동 반응형

Grid 속성 치트시트

속성대상설명
display: gridContainerGrid 활성화
grid-template-columnsContainer열 정의
grid-template-rowsContainer행 정의
grid-template-areasContainer영역 정의
gapContainer간격
justify-itemsContainer셀 내 수평 정렬
align-itemsContainer셀 내 수직 정렬
justify-contentContainer그리드 전체 수평 정렬
align-contentContainer그리드 전체 수직 정렬
grid-auto-flowContainer자동 배치 방향
grid-auto-rowsContainer자동 행 크기
grid-columnItem열 위치
grid-rowItem행 위치
grid-areaItem영역 이름
justify-selfItem개별 수평 정렬
align-selfItem개별 수직 정렬

실전 팁

  1. repeat(): 반복 패턴 간단하게
  2. fr 단위: 비율 기반 레이아웃
  3. minmax(): 최소/최대 크기 제한
  4. auto-fill: 공간에 맞춰 자동 채우기
  5. grid-template-areas: 직관적인 레이아웃 정의
  6. gap: margin보다 간단
  7. span: 여러 칸 차지
  8. -1: 마지막 라인 참조
  9. Chrome DevTools: Grid 디버깅 도구 활용
  10. Flexbox와 조합: Grid로 전체, Flexbox로 세부

다음 단계

  • 반응형 웹 디자인
  • CSS 애니메이션
  • JavaScript와 함께 사용하기

관련 글

  • CSS 박스 모델 | Margin, Padding, Border 완벽 정리
  • CSS Flexbox | 플렉스박스 레이아웃 완벽 가이드
  • HTML/CSS 시작하기 | 웹 개발 첫걸음
  • CSS 기초 | 선택자, 속성, 색상, 폰트
  • 반응형 웹 디자인 | 미디어 쿼리와 모바일 최적화