CSS 독학 가이드 4 - Grid 레이아웃

learning by Seven Fingers Studio 21분
CSSGrid레이아웃그리드2차원레이아웃

Grid가 등장한 이유

Flexbox로 대부분의 레이아웃은 해결되지만, 복잡한 2차원 레이아웃(행과 열을 동시에 제어)은 여전히 까다로웠어요.

예를 들어 이런 레이아웃을 만든다고 생각해보세요:

헤더
사이드바
메인
푸터

Flexbox로도 가능하지만 중첩이 필요해요. Grid는 이걸 한 번에 해결합니다!

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>
.container {
  display: grid;
  grid-template-columns: 200px 200px 200px;  /* 3개 열 */
  grid-template-rows: 100px 100px;           /* 2개 행 */
  gap: 10px;
}

실행 결과:

1
2
3
4
5
6

이렇게만 해도 2행 3열 그리드가 완성됩니다!

행과 열 정의하기

1. 고정 크기

.container {
  display: grid;
  grid-template-columns: 100px 200px 300px;  /* 각각 다른 크기 */
}

2. fr 단위 (fraction) ⭐ 가장 많이 씀

남은 공간을 비율로 나눠요.

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;  /* 1:2:1 비율 */
}

실행 결과:

1fr
2fr (2배 넓음)
1fr

가운데 열이 나머지보다 2배 넓어집니다!

3. repeat() 함수

같은 값 반복할 때 편해요.

/* 이전 방식 */
grid-template-columns: 1fr 1fr 1fr 1fr;

/* repeat 사용 */
grid-template-columns: repeat(4, 1fr);  /* 4개 열, 각 1fr */

실행 결과:

1
2
3
4

4개의 열이 균등하게 배치됩니다

4. auto-fit / auto-fill ⭐ 반응형에 필수

화면 크기에 맞춰 자동으로 열 개수가 조정돼요.

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

실행 결과:

카드 1
카드 2
카드 3

브라우저 창 크기를 조절하면 자동으로 열 개수가 변경됩니다

  • 최소 250px
  • 공간이 있으면 늘어남
  • 공간이 부족하면 자동으로 다음 줄로

미디어 쿼리 없이 반응형 완성!

간격(Gap)

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;  /* 행과 열 간격 모두 20px */
}

실행 결과:

A
B
C
D
E
F

모든 아이템 사이에 20px 간격이 있습니다

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  row-gap: 30px;     /* 행 간격 */
  column-gap: 20px;  /* 열 간격 */
}

아이템 배치

1. grid-column / grid-row

아이템이 차지할 공간을 지정해요.

.item1 {
  grid-column: 1 / 3;  /* 1번 선부터 3번 선까지 (2칸 차지) */
}

선(Line) 번호:

1 2 3 4
A
B
C

빨간색 선이 그리드 라인 번호예요. A는 1번 선부터 2번 선까지 차지합니다.

/* 더 간단한 방법 */
.item1 {
  grid-column: span 2;  /* 2칸 차지 */
}

실행 결과:

2칸 차지 (span 2)
C
D
E
F

첫 번째 아이템이 2칸을 차지합니다

2. 실전 예제: 헤더가 전체 너비

<div class="layout">
  <header>Header</header>
  <aside>Sidebar</aside>
  <main>Main</main>
  <footer>Footer</footer>
</div>
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  gap: 10px;
}

header {
  grid-column: 1 / 3;  /* 1열부터 3열까지 (전체 너비) */
  background: #333;
  color: white;
  padding: 1rem;
}

aside {
  background: #f0f0f0;
  padding: 1rem;
}

main {
  background: white;
  padding: 2rem;
}

footer {
  grid-column: 1 / 3;  /* 전체 너비 */
  background: #333;
  color: white;
  padding: 1rem;
}

실행 결과:

Header (전체 너비)
Sidebar
Main Content
Footer (전체 너비)

grid-template-areas (이름으로 배치)

더 직관적인 방법이에요!

.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 10px;
  min-height: 100vh;
}

header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }

실행 결과:

Header
Sidebar
Main Content
Footer

grid-template-areas로 명확하게 레이아웃을 정의했습니다

시각적으로 레이아웃이 보이죠? 유지보수하기 엄청 편해요!

아이템 정렬

Container 정렬 (모든 아이템)

.container {
  display: grid;
  justify-items: center;  /* 가로 정렬 */
  align-items: center;    /* 세로 정렬 */
}

실행 결과:

중앙
중앙
중앙

모든 아이템이 셀 중앙에 배치됩니다

옵션: start, end, center, stretch

개별 아이템 정렬

.item1 {
  justify-self: end;    /* 이 아이템만 오른쪽 정렬 */
  align-self: center;   /* 이 아이템만 세로 중앙 */
}

전체 Grid 정렬

Grid 전체를 컨테이너 안에서 정렬해요.

.container {
  display: grid;
  grid-template-columns: repeat(3, 200px);
  justify-content: center;  /* Grid 자체를 가로 중앙 */
  align-content: center;    /* Grid 자체를 세로 중앙 */
  height: 100vh;
}

실전 예제 1: 사진 갤러리

<div class="gallery">
  <img src="1.jpg" alt="">
  <img src="2.jpg" alt="" class="wide">
  <img src="3.jpg" alt="">
  <img src="4.jpg" alt="" class="tall">
  <img src="5.jpg" alt="">
  <img src="6.jpg" alt="">
</div>
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  grid-auto-rows: 200px;  /* 행 높이 명시 */
  gap: 15px;
}

.gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 8px;
}

/* 특정 이미지만 크게 */
.wide {
  grid-column: span 2;
}

.tall {
  grid-row: span 2;
}

실행 결과:

이미지 1
넓은 이미지 (wide)
이미지 3
높은
이미지
(tall)
이미지 5
이미지 6

특정 이미지만 크게 표시하는 갤러리 레이아웃 (넓은 이미지는 2칸, 높은 이미지는 2행을 차지)

Pinterest 스타일 갤러리 완성!

실전 예제 2: 카드 그리드

<div class="card-grid">
  <div class="card">Card 1</div>
  <div class="card featured">Featured</div>
  <div class="card">Card 3</div>
  <div class="card">Card 4</div>
  <div class="card">Card 5</div>
</div>
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

.card {
  background: white;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 2rem;
  min-height: 200px;
}

/* 강조 카드는 2칸 차지 */
.featured {
  grid-column: span 2;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

실행 결과:

Card 1
Featured (2칸 차지)
Card 3
Card 4
Card 5

강조 카드가 2배 넓게 표시됩니다

실전 예제 3: 대시보드 레이아웃

<div class="dashboard">
  <header>Dashboard</header>
  <nav>Menu</nav>
  <main>Main Content</main>
  <aside>Widget</aside>
  <footer>Footer</footer>
</div>
.dashboard {
  display: grid;
  grid-template-columns: 200px 1fr 250px;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header header header"
    "nav main aside"
    "nav footer footer";
  gap: 10px;
  height: 100vh;
}

header {
  grid-area: header;
  background: #2c3e50;
  color: white;
  padding: 1rem;
  display: flex;
  align-items: center;
}

nav {
  grid-area: nav;
  background: #34495e;
  color: white;
  padding: 1rem;
}

main {
  grid-area: main;
  background: white;
  padding: 2rem;
  overflow-y: auto;
}

aside {
  grid-area: aside;
  background: #ecf0f1;
  padding: 1rem;
}

footer {
  grid-area: footer;
  background: #2c3e50;
  color: white;
  padding: 1rem;
  display: flex;
  align-items: center;
}

실행 결과:

Dashboard Header
Navigation

Main Content

대시보드 주요 콘텐츠 영역

Widgets
Footer

전문적인 대시보드 레이아웃을 grid-template-areas로 간단하게 구현

minmax() 함수

최소/최대 크기를 동시에 지정해요.

.container {
  display: grid;
  grid-template-columns: minmax(200px, 400px) 1fr;
}

실행 결과:

minmax(200px, 400px)
1fr (남은 공간)

왼쪽 열은 최소 200px, 최대 400px로 제한됩니다

첫 번째 열은 최소 200px, 최대 400px까지만 늘어납니다.

/* 반응형 그리드의 정석 */
.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

Grid vs Flexbox 선택 기준

Flexbox 사용:

  • 1차원 레이아웃 (한 줄 또는 한 열)
  • 요소 크기가 불규칙적
  • 아이템 순서가 중요
  • 예: 네비게이션 바, 버튼 그룹

Grid 사용:

  • 2차원 레이아웃 (행과 열 동시)
  • 정확한 위치 지정 필요
  • 전체 페이지 레이아웃
  • 예: 대시보드, 갤러리, 복잡한 페이지

실무 팁: 대부분은 둘 다 섞어 씁니다. Grid로 전체 레이아웃 잡고, 각 영역 안에서 Flexbox 사용!

.container {
  display: grid;  /* 전체 레이아웃 */
  grid-template-columns: 1fr 3fr;
}

.header {
  display: flex;  /* 헤더 내부는 Flexbox */
  justify-content: space-between;
}

반응형 Grid 패턴

패턴 1: 자동 조정

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

미디어 쿼리 필요 없음!

패턴 2: 미디어 쿼리 활용

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

@media (max-width: 1024px) {
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 768px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 480px) {
  .grid {
    grid-template-columns: 1fr;
  }
}

개발자 도구로 Grid 확인하기

F12 누르고 grid 컨테이너 선택하면 grid 아이콘이 보여요. 클릭하면:

  • 그리드 라인이 화면에 표시됨
  • 행/열 번호 확인 가능
  • 영역(area) 이름 표시

Grid 배울 때 개발자 도구 없으면 정말 힘들어요!

다음 단계

Grid 레이아웃을 마스터했으니 이제 색상과 타이포그래피를 배울 차례예요. 기능적인 레이아웃에 시각적 디자인을 입히는 법을 배워봅시다.

다음 글에서는 색상 표현 방법, 그라디언트, 폰트 스타일링, 텍스트 효과 등을 다룰 거예요!

실습 과제:

  • 3행 4열 그리드 만들어보기
  • 특정 아이템이 2칸 차지하게 만들기
  • auto-fit으로 반응형 카드 그리드 만들기
  • grid-template-areas로 블로그 레이아웃 만들기

Grid Playground 같은 온라인 도구로 연습하면 더 빨리 배울 수 있어요!

시리즈 네비게이션

← 블로그 목록으로