안녕하세요! 프론트엔드 개발의 꽃, 레이아웃의 끝판왕인 CSS 그리드(Grid)의 세계에 오신 것을 환영합니다.
과거 웹 개발자들은 표(table)나 플로트(float), 심지어 포지셔닝(position)을 억지로 짜깁기해서 복잡한 웹페이지 레이아웃을 만들며 고통받아 왔습니다. 하지만 CSS 그리드가 등장하면서 이 모든 고통이 끝났죠!
마치 모눈종이 위에 레고 블록을 놓듯, 행과 열을 자유롭게 그리고 그 안에 요소를 쏙쏙 넣을 수 있는 혁명적인 레이아웃 시스템입니다. 실무에서 복잡한 대시보드나 매거진 스타일의 웹사이트를 만들 때 절대 빠질 수 없는 필수 기술이니, 저와 함께 완벽하게 마스터해 봅시다!
이전 페이지 (Test your skills: Flexbox) | 개요: CSS 레이아웃 | 다음 페이지 (Test your skills: Grid)
CSS 그리드 레이아웃(Grid Layout)은 웹을 위한 2차원(two-dimensional) 레이아웃 시스템입니다. 즉, 가로(행)와 세로(열)를 동시에 제어할 수 있죠! 이 시스템은 콘텐츠를 행(rows)과 열(columns)로 구성할 수 있게 해주며, 복잡한 레이아웃을 아주 쉽게 만들 수 있도록 수많은 기능들을 제공합니다. 이 글에서는 여러분이 그리드 레이아웃을 시작하기 위해 알아야 할 모든 것을 설명해 드릴 겁니다.
| 사전 준비 지식: | HTML로 콘텐츠 구조화하기, CSS 스타일링 기초, 기본 텍스트 및 폰트 스타일링, CSS 레이아웃 기초 개념에 대한 친숙함. |
| 학습 목표: |
|
그리드(Grid)는 우리가 디자인 요소들을 나란히 줄 세울 수 있도록 패턴을 만들어주는 '가로선과 세로선들의 집합'입니다. 그리드는 우리가 페이지를 이리저리 이동하더라도 요소들이 이리저리 튀거나 너비가 갑자기 변하지 않도록 꽉 잡아주어, 웹사이트 전체에 걸쳐 훌륭한 일관성(consistency)을 제공합니다.
전형적인 그리드는 열(columns)과 행(rows)을 가지고 있으며, 각 행과 열 사이에는 간격이 있습니다. 이 간격들을 보통 거터(gutters)라고 부릅니다.

💡 강사의 실무 팁! (Flexbox vs Grid)
"어? 이전 시간에 배운 Flexbox랑 뭐가 다르죠?"
프론트엔드 면접 1순위 질문입니다! 가장 큰 차이는 차원(Dimension)입니다.
- Flexbox는 1차원입니다. 가로(Row)로 줄을 세우거나, 세로(Column)로 줄을 세우는 것 중 하나만 할 수 있습니다.
- Grid는 2차원입니다. 바둑판처럼 가로와 세로를 동시에 제어해서 요소들을 배치할 수 있습니다.
그래서 실무에서는 웹사이트의 큰 틀(헤더, 사이드바, 본문, 푸터)을 잡을 때는 Grid를 쓰고, 그 안에 들어가는 자잘한 버튼이나 네비게이션 메뉴를 한 줄로 예쁘게 정렬할 때는 Flexbox를 혼합해서 사용하는 것이 가장 완벽한 조합입니다!
여러분의 디자인에 어떤 형태의 그리드가 필요한지 결정했다면, 이제 CSS 그리드 레이아웃을 사용해 그것을 실제로 만들어 볼 차례입니다. 먼저 그리드 레이아웃의 기본적인 기능들을 살펴보고, 그다음 프로젝트를 위한 간단한 그리드 시스템을 어떻게 만드는지 알아보겠습니다.
그리드 레이아웃을 직접 테스트해 봅시다. 여기 부모 컨테이너(div.container)와 그 안에 여러 개의 자식 아이템들(div)이 있는 예제가 있습니다. 기본적으로 이 아이템들은 정상적인 흐름(normal flow)에 따라 블록 요소로 렌더링되므로, 화면에 하나씩 세로로 차곡차곡 쌓이게 됩니다.
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
</div>
body {
font-family: sans-serif;
}
.container > div {
border-radius: 5px;
padding: 10px;
background-color: rgb(207 232 220);
border: 2px solid rgb(79 185 227);
}
Flexbox를 사용할 때와 마찬가지로, 그리드 레이아웃을 정의하려면 부모 컨테이너의 display 속성값을 grid로 설정하면 됩니다. display: grid 속성은 컨테이너의 모든 직계 자식(direct children)들을 마법처럼 '그리드 아이템(grid items)'으로 변신시킵니다. 파일에 다음 CSS를 추가해 보죠:
.container {
display: grid;
}
하지만 놀랍게도, (Flexbox와는 달리) 화면 속 아이템들은 당장 아무런 변화도 보이지 않을 것입니다. display: grid만 덜렁 선언하면 브라우저는 기본적으로 '1개의 열(column)만 있는 그리드'를 만들어냅니다. 그래서 정상 흐름일 때처럼 아이템들이 여전히 하나씩 아래로 쌓여있는 것이죠.
이 녀석이 정말 그리드처럼 보이게 하려면, 그리드에 열(columns)을 추가해 줘야 합니다. 가로 200픽셀짜리 열을 3개 만들어 볼까요? 이 열 트랙(column tracks)을 만들 때는 px, em, % 등 어떤 길이 단위든 자유롭게 사용할 수 있습니다.
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
}
이제 저장하고 확인해 보시면, 아이템들이 그리드의 각 셀 안으로 쏙쏙 들어가면서 3열로 예쁘게 재배열된 것을 보실 수 있을 겁니다! 첫 번째 줄에 3개가 꽉 차면, 나머지는 알아서 다음 줄(행)로 넘어가서 배치됩니다.
(브라우저 렌더링 화면: 1~3이 첫 줄, 4~6이 두 번째 줄, 7이 세 번째 줄에 200px 간격으로 나란히 배치된 모습)
잠깐 쉬어갈까요? ScrimbaMDN 학습 파트너에서 제공하는 아래의 인터랙티브 레슨을 통해 CSS 그리드의 기본을 직접 만져보며 복습할 수 있습니다. 어떻게 코드가 작동하는지 라이브 그리드 예제를 플레이해 보세요!
📝 참고사항 (Note):
Scrimba의 'Your first grid' 인터랙티브 레슨 플레이하기
우리는 px이나 % 같은 고정/상대 길이 단위를 넘어, Grid에서만 쓸 수 있는 마법의 단위인 fr (fraction, 비율) 단위를 사용할 수 있습니다. fr 단위는 그리드 컨테이너 내에서 "사용 가능한 남는 공간(available space)의 한 조각(fraction)"을 의미하며, 그리드의 행과 열 크기를 엄청나게 유연하게 조절할 수 있게 해 줍니다.
아래 코드처럼 트랙 정의를 1fr 3개로 변경해 보겠습니다:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
결과를 보면 아까 200px로 고정했을 때와 달리, 세 개의 열이 브라우저 화면(컨테이너)의 너비 전체를 1:1:1 비율로 공평하게 나누어 가득 채우고 있는 것을 볼 수 있습니다.
이 fr 단위는 남는 공간을 비율대로 분배하는 것이기 때문에, 서로 다른 비율의 숫자들을 섞어서 사용할 수 있습니다. 아래 코드로 트랙 정의를 변경해 보세요. 첫 번째 열은 2fr, 나머지 두 열은 1fr입니다:
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
}
이제 첫 번째 트랙은 나머지 트랙들보다 두 배 더 넓은 공간을 차지하게 됩니다.
게다가 fr 단위는 고정된 길이 단위(px 등)와 마구 섞어서 쓸 수도 있습니다! 예를 들어 grid-template-columns: 200px 1fr 2fr; 이라고 적었다면, 브라우저는 가장 먼저 첫 번째 열에 고정폭 200px을 빼놓은 다음, 나머지 남은 공간을 두 번째와 세 번째 열에 1:2의 비율로 나눠주게 됩니다. 정말 똑똑하죠?
⚠️ 강사의 주의사항! (Note):
fr단위는 컨테이너의 전체 공간을 나누는 게 아니라, 텍스트나 이미지가 차지하고 남은 사용 가능한(available) 빈 공간을 나눈다는 사실을 절대 잊지 마세요. 만약 어떤 트랙 안에 크기가 어마어마하게 큰 이미지가 들어있다면, 그 녀석이 자리를 떡하니 다 차지해 버려서 다른fr트랙들에게 돌아갈 빈 공간이 쪼그라들게 됩니다.
행과 열 사이의 간격(거터)을 만들려면 다음 속성들을 사용합니다:
column-gap: 열(가로) 사이의 간격row-gap: 행(세로) 사이의 간격gap: 위 두 가지를 한 번에 설정하는 단축 속성 (예: gap: 20px; 또는 gap: 20px 10px;)트랙 사이에 20px의 간격을 만들어 볼까요?
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: 20px;
}
💡 강사의 실무 팁! (Gap의 위력)
예전에는 아이템 사이를 띄우려고margin-right나margin-bottom을 주고, 맨 마지막 아이템은 다시 마진을 빼주는(:last-child { margin: 0; }) 번거로운 짓을 해야 했습니다. 하지만 이제gap속성 하나면 아이템 사이사이에만 깔끔하게 여백이 들어갑니다. 최고예요!
단,gap의 값으로는 px, em, % 등은 쓸 수 있지만fr단위는 절대 사용할 수 없습니다.
컬럼이 12개쯤 필요한데 1fr 1fr 1fr ... 이렇게 12번을 치고 있으면 손가락이 아프겠죠? 이럴 때 CSS의 repeat() 함수를 사용하면 트랙 리스트의 전체 또는 일부 구간을 아주 쉽게 반복시킬 수 있습니다.
위의 코드를 다음과 같이 바꿔볼게요:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
결과는 아까 1fr 1fr 1fr이라고 적었을 때와 완벽하게 똑같습니다. repeat() 함수의 첫 번째 인자(3)는 몇 번을 반복할 것인지 횟수를 지정하고, 두 번째 인자(1fr)는 반복할 트랙의 크기(또는 크기 패턴)를 지정합니다.
지금까지 우리는 열(column) 트랙만 명시적으로 지정했습니다. 하지만 아이템들은 넘칠 때마다 알아서 새로운 행(row)을 뚫고 들어가 배치되었죠. 여기서 바로 명시적 그리드(explicit grid)와 암시적 그리드(implicit grid)의 차이가 등장합니다.
grid-template-columns나 grid-template-rows를 사용해서 "나는 3칸짜리 열과 2칸짜리 행을 만들 거야!"라고 선언해서 만들어진 그리드입니다.기본적으로 브라우저가 몰래 만들어내는 암시적 그리드 트랙들의 크기는 auto로 설정되어 있습니다. 이 말은 즉, 그 안에 들어가는 내용물(글자 등)의 높이에 맞춰 쪼잔하게 늘어난다는 뜻입니다. 만약 브라우저가 자동으로 생성하는 이 암시적 행들의 높이를 내가 원하는 대로 큼직하게 고정하고 싶다면, grid-auto-rows 속성을 사용하면 됩니다! (열을 제어하고 싶다면 grid-auto-columns를 씁니다.)
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
gap: 20px;
}
이제 4번, 5번, 6번 등 새롭게 자동 생성된 줄(행)들의 높이도 얄짤없이 100px로 고정된 것을 보실 수 있을 겁니다.
방금 만든 100px짜리 고정 행은 사실 꽤 위험합니다. 만약 100px보다 훨씬 긴 텍스트를 그 안에 집어넣게 되면, 내용이 100px 상자 밖으로 삐져나오는 오버플로우(overflow) 대참사가 일어날 테니까요. 웹 개발의 진리는 "이 안에 내용물이 얼마나 길어질지 절대 100% 확신할 수 없다"는 것입니다. 모든 크기를 픽셀로 완벽하게 꿰어 맞추려는(pixel-perfect) 디자인은 내용이 추가되거나 사용자가 폰트 크기를 키우면 바로 박살 납니다.
이때 우리의 구원자, minmax() 함수가 등장합니다! 이 함수는 트랙의 최소 크기와 최대 크기의 한계선을 설정해 줍니다.
예를 들어 minmax(100px, auto)라고 적으면, "아무리 내용이 없어도 최소 100px의 높이는 무조건 지켜! 하지만 내용물이 100px을 넘어서 길어지면? 쿨하게 내용물에 맞춰서(auto) 쭉 늘어나!"라는 환상적인 지시를 내리게 됩니다.
코드를 이렇게 바꿔볼까요?
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
gap: 20px;
}
이제 HTML에 내용을 잔뜩 추가해 보면, 내용이 길어진 트랙만 100px을 넘어서 자연스럽게 위아래로 확장되는 것을 볼 수 있습니다. (그리고 그리드 행의 특성상, 같은 줄에 있는 옆 칸들도 그 늘어난 높이에 맞춰 다 같이 사이좋게 길어집니다!)
지금까지 배운 repeat(), minmax(), 그리고 fr 단위를 모두 하나로 합치면, 미디어 쿼리(@media)를 단 한 줄도 쓰지 않고 반응형 레이아웃을 뚝딱 만들어내는 전설의 마법 공식이 탄생합니다!
"화면이 허용하는 한 최대한 많은 열을 만들어줘!"라고 브라우저에게 부탁하는 건데요, grid-template-columns에 repeat() 함수를 쓰되, 반복 횟수에 숫자 대신 auto-fit 이라는 마법의 키워드를 넣습니다. 그리고 두 번째 인자로 minmax(최소너비, 1fr)를 넣어줍니다.
💡 강사의 실무 팁! (카드 레이아웃의 성배)
쇼핑몰 상품 리스트나 블로그 글 목록(카드 형태)을 만들 때 실무에서 100% 쓰이는 마법의 코드입니다. 눈에 콕 박아두세요!
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
grid-auto-rows: minmax(50px, auto);
gap: 20px;
}
이 코드가 작동하는 원리는 이렇습니다. 브라우저는 컨테이너 너비를 확인한 다음, "가로가 최소 230px인 카드를 이 안에 몇 개나 우겨넣을 수 있지?"를 계산합니다. 만약 화면이 넓어서 230px 카드가 4개 들어가고도 공간이 살짝 남는다면? 남은 공간을 4개의 카드에 1fr씩 똑같이 분배해서 화면을 꽉 차게 예쁘게 늘려줍니다. 화면을 줄여서 공간이 부족해지면 3개, 2개, 1개로 알아서 줄바꿈 되며 렌더링 됩니다. 정말 훌륭하죠!
지금까지는 브라우저가 알아서 빈칸에 요소를 하나씩 욱여넣는 '자동 배치'만 보았습니다. 이제는 그리드의 격자 위에 원하는 요소를 내가 원하는 위치에 콕 집어서 배치하는 방법을 배워보겠습니다.
그리드에는 항상 라인(Lines, 선)들이 존재합니다. 이 선들은 1번부터 시작해서 번호가 매겨지며, 문서의 쓰기 모드(writing mode) 방향에 따라 달라집니다. 기본 왼쪽에서 오른쪽으로 읽는 영어/한국어 환경에서는, 가로(열) 선 1번은 그리드의 맨 왼쪽 테두리 선이고, 세로(행) 선 1번은 맨 위쪽 테두리 선입니다.
아이템을 이 선들을 따라 배치하기 위해, 아이템이 어느 선에서 시작하고 어느 선에서 끝날지를 지정할 수 있습니다. 4가지 속성이 사용됩니다:
grid-column-start: 열 시작 선 번호grid-column-end: 열 끝 선 번호grid-row-start: 행 시작 선 번호grid-row-end: 행 끝 선 번호이 속성들에 선 번호를 값으로 주면, "이 아이템은 1번 세로선에서 시작해서 3번 세로선에서 끝나게 해 줘!"라고 지시할 수 있습니다.
매번 4줄을 쓰기 귀찮으니, 시작 선과 끝 선을 슬래시(/)로 구분해서 한 방에 적는 단축 속성을 훨씬 더 많이 씁니다:
grid-column (column start / end 단축)grid-row (row start / end 단축)이해를 돕기 위해 전형적인 웹사이트 레이아웃 HTML 구조를 가져와 볼게요. Header, Main, Aside, Footer가 있습니다.
<div class="container">
<header>Header</header>
<main>
<h1>Main</h1>
<p>Main content…</p>
</main>
<aside>
<h2>Aside</h2>
<p>Related content</p>
</aside>
<footer>footer</footer>
</div>
부모 컨테이너에 그리드를 정의해 둡니다.
.container {
font-family: sans-serif;
display: grid;
grid-template-columns: 1fr 3fr; /* 2개의 열, 1:3 비율 */
gap: 20px;
}
/* 기타 예쁘게 보이게 하는 장식 스타일 생략... */
위 상태 그대로라면 브라우저는 header를 첫 번째 칸에, main을 두 번째 칸에 자동 배치해서 화면을 다 망가뜨려 놓을 겁니다. 이제 우리가 라인 배치를 통해 제자리를 찾아줍시다. CSS 맨 밑에 다음 코드를 추가하세요:
header {
grid-column: 1 / 3; /* 세로선 1번부터 3번 선까지(즉, 전체 너비) 차지해! */
grid-row: 1; /* 첫 번째 가로줄에 있어! */
}
main {
grid-column: 2; /* 두 번째 칸에 있어! */
grid-row: 2; /* 두 번째 가로줄에 있어! */
}
aside {
grid-column: 1; /* 첫 번째 칸에 있어! */
grid-row: 2; /* 두 번째 가로줄에 있어 (main이랑 나란히)! */
}
footer {
grid-column: 1 / 3; /* 세로선 1번부터 3번 선까지 쫙 늘어나! */
grid-row: 3; /* 세 번째 가로줄에 있어! */
}
이제 <header>와 <footer>는 grid-column: 1 / 3; 속성 덕분에 세로 1번 선부터 3번 선(우리가 2열을 만들었으니, 3번 선이 맨 오른쪽 끝 선입니다)까지 가로로 쫙 늘어나서 자리 잡게 되었습니다!
💡 강사의 꿀팁! (끝에서부터 세기)
"컬럼이 너무 많아서 맨 끝 선 번호가 몇 번인지 세기 귀찮아요!"
그럴 때는 음수 값-1을 사용하면 됩니다.-1은 "명시적 그리드의 맨 끝 선"을 의미합니다. 따라서 헤더를 끝까지 쫙 늘리고 싶다면grid-column: 1 / -1;이라고 적으시면 컬럼이 몇 개든 상관없이 항상 100%를 차지하게 됩니다!
번호를 세어가며 배치하는 것도 좋지만, 숫자만 봐서는 이 레이아웃이 어떻게 생겼는지 한눈에 파악하기 어렵습니다. 이럴 때 쓸 수 있는 아주 직관적이고 시적인(?) 대안이 바로 grid-template-areas 속성을 사용하여 디자인의 각 영역에 '이름표'를 붙여주는 방법입니다.
바로 코드를 볼까요? 아까의 숫자 배치를 지우고, 대신 이렇게 바꿔보세요:
.container {
display: grid;
/* 마법이 시작되는 곳입니다! */
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
grid-template-columns: 1fr 3fr;
gap: 20px;
}
header {
grid-area: header; /* 내 이름은 header야! */
}
main {
grid-area: content; /* 내 이름은 content야! */
}
aside {
grid-area: sidebar; /* 내 이름은 sidebar야! */
}
footer {
grid-area: footer; /* 내 이름은 footer야! */
}
어떤가요? 자식 요소들의 grid-area 속성에 자기 이름표를 달아주면, 부모 컨테이너의 grid-template-areas 안에 적어둔 큰 따옴표(" ") 그림판에 그 이름들이 블록처럼 쏙쏙 들어가 박힙니다! CSS 코드 형태 자체가 실제 화면 레이아웃의 축소판처럼 생겨서, 다른 개발자가 봐도 1초 만에 "아, 헤더랑 푸터가 가로를 꽉 채우고 중간에 사이드바랑 본문이 있구나!" 하고 이해할 수 있습니다.
grid-template-areas를 작성할 때 지켜야 할 규칙은 다음과 같습니다:
. )를 찍으면 됩니다.💡 강사의 실무 팁!
실무에서 미디어 쿼리와 함께 이grid-template-areas를 쓰면 진가를 발휘합니다. 모바일 화면일 때는 세로로 쭉 나열되게"header" "content" "sidebar" "footer"라고 적어두고, PC 화면(@media (min-width: 768px))일 때만 위의 코드처럼 2열 구조로 확 바꿔치기하면, HTML 코드는 하나도 안 건드리고 완벽한 반응형 레이아웃을 만들 수 있습니다!
그리드 아이템(자식)에게 다시 display: grid를 주면, 그 아이템은 자신의 부모이자 동시에 또 다른 그리드의 부모(중첩된 그리드, Nested Grid)가 됩니다.
하지만 일반적인 중첩 그리드는 부모 그리드와 '격자(선)'를 공유하지 못하고 각자 따로 놀기 때문에, 부모의 선에 맞춰 자식 안의 아이템들을 정렬하기가 매우 까다로웠습니다. 이 문제를 완벽하게 해결하기 위해 등장한 것이 바로 "서브그리드(subgrid)" 기능입니다!
자식 그리드의 grid-template-columns 나 grid-template-rows 값으로 subgrid라는 키워드를 주면, 이 자식 그리드는 자신만의 새로운 트랙을 쪼개는 대신 부모 그리드의 트랙(선)을 그대로 물려받아서 사용하게 됩니다.
예제를 볼까요? 카드 레이아웃 안에 여러 기사(article)들이 들어있고, 그중 5~8번 기사는 .subgrid라는 클래스로 묶여있는 구조입니다.
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div class="subgrid">
<div>Five</div>
<div>Six</div>
<div>Seven</div>
<div>Eight</div>
</div>
<div>Nine</div>
<div>Ten</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 부모는 4열을 만듭니다 */
grid-template-rows: repeat(1, 1fr);
gap: 10px;
}
.subgrid {
grid-column: 1 / 4; /* 서브그리드 컨테이너가 1~3번 열을 차지하게 늘립니다 */
grid-row: 2 / 4; /* 2~3번 행을 차지하게 늘립니다 */
display: grid; /* 나도 이제 그리드다! */
gap: inherit; /* 부모의 gap을 물려받습니다 */
grid-template-columns: subgrid; /* 핵심!! "가로선은 부모가 쳐놓은 선을 그대로 쓸게!" */
grid-template-rows: 2fr 1fr; /* 하지만 세로줄은 내 맘대로 2:1 비율로 새로 짤게! */
}
결과를 보시면, .subgrid 안쪽에 있는 5~8번 아이템들이 부모가 그어놓은 가로 4열의 가이드라인(선)에 완벽하게 딱 맞춰 정렬되어 있는 것을 볼 수 있습니다. 반면 세로(행) 높이는 자신이 정의한 2fr 1fr 비율대로 움직이고 있죠. 이처럼 subgrid를 쓰면 복잡한 카드 UI 안에 있는 텍스트나 버튼들의 줄을 전체 그리드 차원에서 깔끔하게 정렬할 수 있습니다.
시중에는 이미 만들어져 있는 수많은 그리드 프레임워크(Grid frameworks)들이 존재합니다. Bootstrap이나 Tailwind CSS 같은 것들이 대표적이죠. 이들은 보통 12개나 16개짜리 열 그리드 시스템을 미리 짜두고, 클래스 이름만 HTML에 추가하면 요소 간격, 정렬, 모바일 화면 대응(breakpoints)까지 다 해주도록 만들어져 있습니다.
하지만 좋은 소식이 있습니다! 이제는 모든 모던 브라우저가 CSS Grid 표준을 완벽하게 지원하기 때문에, 외부 프레임워크의 무거운 코드를 억지로 끌고 오지 않아도 순수 CSS만으로 완벽한 그리드 시스템을 직접 만들 수 있습니다.
아래 예제는 여러분이 12-컬럼 그리드 프레임워크를 직접 순수 CSS로 아주 단순하게 구현해 본 모습입니다. grid-template-columns: repeat(12, 1fr);로 12개의 열을 쫙 깔아두고, 앞에서 배운 라인 기반 배치(line-based placement)로 아이템들이 12칸 중 몇 칸씩 차지할지 번호를 매겨주면 끝입니다!
<div class="container">
<header>Header</header>
<main>
<h1>Main</h1>
<p>Main content…</p>
</main>
<aside>
<h2>Aside</h2>
<p>Related content</p>
</aside>
<footer>footer</footer>
</div>
.container {
display: grid;
grid-template-columns: repeat(12, 1fr); /* 12-컬럼 시스템 뚝딱! */
gap: 20px;
}
header {
grid-column: 1 / 13; /* 헤더는 1부터 끝(13번 선)까지 12칸 다 써! */
grid-row: 1;
}
main {
grid-column: 4 / 13; /* 메인 본문은 4번 선부터 끝까지 (9칸) 써! */
grid-row: 2;
}
aside {
grid-column: 1 / 4; /* 사이드바는 1번부터 4번 선 앞까지 (3칸) 써! */
grid-row: 2;
}
footer {
grid-column: 1 / 13; /* 푸터도 12칸 다 써! */
grid-row: 3;
}
💡 강사의 실무 팁!
"와, 그럼 이제 Bootstrap 같은 거 안 써도 되나요?"
네, 레이아웃을 잡는 목적만 놓고 보면 CSS Grid가 훨씬 직관적이고 코드가 깨끗합니다. 물론 프레임워크들은 버튼 디자인이나 모달 같은 부가 기능들을 주니까 쓰지만, 단순 격자 배치를 위해 무거운 라이브러리를 설치하는 시대는 이미 지나갔다고 보셔도 무방합니다. CSS Grid 하나면 충분합니다!
Firefox 브라우저를 쓰신다면 Firefox 그리드 인스펙터(Firefox grid inspector) 도구를 켜서 그리드 선 번호를 화면에 띄워놓고 작업해 보세요. 우리가 만든 12-컬럼 그리드가 어떻게 작동하는지 눈으로 완벽하게 볼 수 있습니다.

이 개요를 통해 우리는 CSS 그리드 레이아웃의 핵심적이고 거대한 기능들을 한 바퀴 둘러보았습니다. 이제 여러분의 디자인에 이 기능들을 적용해 볼 준비가 되셨을 겁니다!
다음 글에서는 지금까지 CSS 그리드에 대해 배운 이 수많은 정보들을 얼마나 잘 이해하고 머릿속에 담아두었는지 확인할 수 있는 테스트들을 제공해 드릴게요. 파이팅입니다!
이전 페이지 (Test your skills: Flexbox) | 개요: CSS 레이아웃 | 다음 페이지 (Test your skills: Grid)