Grid layout/Basic concepts

김동현·2026년 3월 21일

mdn 학습 번역 - CSS

목록 보기
101/190

안녕하세요! 오늘 번역해 볼 MDN 공식 문서는 CSS 레이아웃의 끝판왕이자 가장 강력한 도구인 그리드 레이아웃의 기본 개념(Basic concepts of grid layout)입니다.

프론트엔드 개발자로 취업을 준비하시다 보면, 복잡한 대시보드 화면이나 책 갤러리 뷰 등을 만들 때 Flexbox만으로는 한계를 느끼는 순간이 오게 마련입니다. 1차원 배치를 담당하는 Flexbox와 달리, 행(Row)과 열(Column)을 동시에 다루는 2차원 배치를 가능하게 해주는 것이 바로 CSS Grid입니다.

기술 면접에서도 "Flexbox와 Grid의 차이점이 무엇인가요?"라는 질문은 아주 빈출되는 주제이니, 이 문서를 통해 Grid만의 고유한 용어와 작동 방식을 확실하게 정리해 두시길 추천해 드립니다!


그리드 레이아웃의 기본 개념 (Basic concepts of grid layout)

CSS 그리드 레이아웃(CSS grid layout)은 CSS에 2차원(two-dimensional) 그리드 시스템을 도입했습니다. 그리드는 웹 페이지의 큼직한 주요 영역을 배치하는 데 사용할 수도 있고, 아주 작은 사용자 인터페이스 요소들을 배치하는 데 사용할 수도 있습니다. 이 가이드에서는 CSS 그리드 레이아웃의 핵심적인 특징과, 이 명세서에서 사용되는 주요 전문 용어(terminology)들을 소개합니다. 이 개요에서 살펴본 기능들은 이 시리즈의 다른 가이드들에서 더욱 자세하게 다루어질 것입니다.

이 문서에서 다룰 내용 (In this article)


그리드란 무엇인가요? (What is a grid?)

그리드는 행(rows)과 열(columns)을 정의하는 수평선과 수직선들이 교차하는 집합입니다. 요소들은 이 행과 열을 이루는 선들(lines) 안쪽으로 그리드 상에 배치될 수 있습니다. CSS 그리드 레이아웃은 다음과 같은 특징들을 제공합니다:

고정 및 유연한 트랙 크기 (Fixed and flexible track sizes)

예를 들어 픽셀(pixels)을 사용하여 고정된 크기의 트랙을 가진 그리드를 만들 수 있습니다. 이렇게 하면 여러분이 원하는 특정 픽셀 크기에 딱 들어맞는 레이아웃이 설정됩니다. 또한 퍼센트(%)나 이 목적을 위해 특별히 고안된 fr 단위를 사용하여 유연하게 크기가 변하는 그리드를 만들 수도 있습니다.

아이템 배치 (Item placement)

줄 번호(line numbers)나 이름(names)을 사용하거나, 혹은 그리드의 특정 영역(area)을 직접 지정하는 방식으로 아이템을 그리드 상의 아주 정확한 위치에 배치할 수 있습니다. 또한, 그리드는 명시적인 위치가 주어지지 않은 아이템들을 어떻게 배치할지 스스로 결정하는 알고리즘(auto-placement)도 포함하고 있습니다.

콘텐츠를 담기 위한 추가 트랙 생성 (Creation of additional tracks to hold content)

여러분은 그리드 레이아웃으로 명시적 그리드(explicit grid)를 정의할 수 있습니다. 그리고 필요할 때 자동으로 추가적인 행이나 열을 덧붙이는 유연성도 가지고 있습니다. 예를 들어 "컨테이너 안에 들어갈 수 있는 한 최대한 많은 열 추가하기"와 같은 강력한 기능들이 포함되어 있습니다.

정렬 제어 (Alignment control)

CSS 그리드 레이아웃과 CSS 박스 정렬(CSS box alignment) 기능들을 결합하면, 아이템들이 특정 그리드 영역에 배치되었을 때 그 안에서 어떻게 정렬될 것인지, 그리고 전체 그리드 자체가 컨테이너 안에서 어떻게 정렬될 것인지를 정교하게 제어할 수 있습니다.

겹치는 콘텐츠 제어 (Control of overlapping content)

하나 이상의 아이템을 동일한 그리드 셀이나 영역에 배치할 수 있으며, 이들은 부분적으로 겹쳐질 수 있습니다. 이렇게 겹쳐진 레이어들은 z-index 속성을 이용해 어느 것이 위에 올지 제어할 수 있습니다.

그리드는 플렉스박스(flexbox)와 같은 CSS의 다른 요소들과 결합되었을 때, 반응형(responsive)이고 유연하며 접근성(accessible)이 뛰어난 레이아웃을 만들 수 있도록 도와주는 매우 강력한 방법입니다. 이 모든 것은 그리드 컨테이너(grid container)를 만드는 것에서부터 시작합니다.


그리드 컨테이너 (Grid container)

요소에 display: grid 또는 display: inline-grid를 선언하면 그리드 컨테이너가 생성됩니다. 이렇게 선언하는 즉시, 해당 요소의 모든 직계 자식(direct children)들은 그리드 아이템(grid items)이 됩니다.

다음 예제에는 wrapper라는 클래스를 가진 묶음 div(컨테이너)가 있고, 그 내부에 5개의 자식 요소들이 중첩되어 있습니다.

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>

우리는 display: grid;를 사용하여 .wrapper를 그리드 컨테이너로 만듭니다.

.wrapper {
  display: grid;
}

이제 이 모든 직계 자식들은 그리드 아이템이 되었습니다. 하지만 웹 브라우저에서 봤을 때, 요소들을 그리드로 변환하기 전과 화면상에 나타나는 방식에서 아무런 차이도 느끼지 못할 것입니다. 이는 그리드가 이 아이템들을 위해 기본적인 단일 열(1단) 그리드를 생성했기 때문입니다. 만약 여러분의 브라우저 개발자 도구(developer tools)에서 이 그리드를 검사해 보면, grid라는 값 옆에 작은 아이콘이 있는 것을 볼 수 있습니다. 그것을 클릭하면 대부분의 브라우저에서 현재 창 위에 그리드 선들이 오버레이(overlaid) 되어 나타납니다.

Using the grid highlighter in Firefox DevTools to view a grid

💡 강사의 실무 팁!
"Grid는 눈에 보이지 않아서 코딩하기가 너무 어려워요"라고 하시는 분들이 많습니다. 그럴 땐 크롬(Chrome)이나 파이어폭스(Firefox)의 개발자 도구를 꼭 활용하세요! Elements 탭에서 grid 배지를 클릭하면 위 사진처럼 모눈종이 형태의 오버레이가 켜지는데, 이것을 켜두고 코딩하면 디버깅 속도가 비약적으로 올라갑니다.

만약 이 레이아웃을 좀 더 우리가 생각하는 전형적인 형태의 '그리드'처럼 만들고 싶다면, 열 트랙(column tracks)을 추가해 주어야 합니다.


그리드 트랙 (Grid tracks)

우리는 grid-template-rowsgrid-template-columns 속성을 사용하여 그리드 상에 행과 열을 정의합니다. 이것들은 그리드 트랙(grid tracks)을 정의하는 역할을 합니다. 그리드 트랙이란 그리드 상에 있는 인접한 두 선 사이의 공간을 말합니다. 아래 이미지는 강조 표시된 트랙을 보여주는데, 이것이 바로 우리 그리드의 '첫 번째 행 트랙'입니다.

A box with 3 grid items. Above the three items is a solid light green area which is the track.

그리드 트랙은 grid-template-columnsgrid-template-rows 속성 (또는 단축 속성인 gridgrid-template)을 사용하여 지정될 때 명시적 그리드(explicit grid) 안에서 정의됩니다. 또한 명시적 그리드에서 지정해 둔 영역 바깥쪽에 그리드 아이템을 배치하려 할 때, 브라우저가 알아서 암시적 그리드(implicit grid)의 트랙을 생성하기도 합니다.

기본 예제 (Basic example)

앞선 예제에 grid-template-columns 속성을 추가한 뒤, 각 열 트랙의 크기를 정의해 줌으로써 열 트랙들을 추가해 보겠습니다.

이제 우리는 각각 200픽셀의 너비를 가진 세 개의 열 트랙을 가진 그리드를 만들었습니다. 자식 아이템들은 이 그리드 상의 각각의 그리드 셀에 하나씩 차례대로 배치될 것입니다.

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: 200px 200px 200px; /* 200px 너비의 열을 3개 생성합니다 */
}

fr 단위 (The fr unit)

트랙은 어떤 길이 단위(px, em, % 등)를 사용해서도 정의할 수 있습니다. 하지만 그리드는 유연한 그리드 트랙을 만드는 데 도움을 주기 위해 아주 새로운 길이 단위를 하나 도입했습니다. 바로 fr (fraction) 단위입니다. 이 단위는 그리드 컨테이너 내에서 사용 가능한 공간의 비율(fraction)을 나타냅니다.

다음 그리드 정의는 가용 공간에 맞춰 자유롭게 늘어나고 줄어드는, 동일한 너비의 3개의 트랙을 생성합니다.

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr; /* 남은 가용 공간을 1:1:1로 나누어 가집니다! */
}

💡 면접 단골 질문!
"Grid에서 사용하는 fr 단위란 무엇인가요?"
모범 답안: "fr은 fraction의 약자로, 그리드 컨테이너 내에서 트랙을 배치하고 남은 '가용 공간(여백)'을 지정한 비율대로 분배할 때 사용하는 단위입니다. 픽셀(px) 같은 고정 단위와 혼합해서 쓸 때, 픽셀이 차지한 공간을 제외한 나머지 영역만 알아서 똑똑하게 계산해 분배해 주기 때문에 반응형 웹을 짤 때 %보다 훨씬 안전하고 편리하게 사용할 수 있습니다."

크기가 다른 트랙 (Unequal sizes)

이번 예제에서는 첫 번째는 2fr, 다음 두 개는 1fr인 트랙 정의를 생성해 봅니다. 가용 공간은 총 4개(2+1+1)의 조각으로 나뉩니다. 첫 번째 트랙에는 두 조각이 주어지고, 나머지 두 트랙에는 각각 한 조각씩 주어지게 됩니다.

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr; /* 첫 번째 열이 두 배 더 넓어집니다. */
}

유연한 크기와 절대 크기 혼합하기 (Mixing flexible and absolute sizes)

마지막 예제로 절대 크기(absolute sized) 트랙과 fr 단위를 혼합해 보겠습니다. 첫 번째 트랙은 500px로 고정됩니다. 그러면 전체 가용 공간에서 이 고정된 500px 너비가 먼저 차감됩니다. 그리고 남은 여유 공간은 세 조각(1+2)으로 나뉘어 두 개의 유연한(fr) 트랙에 비율에 맞게 할당됩니다.

.wrapper {
  display: grid;
  grid-template-columns: 500px 1fr 2fr;
}

repeat() 표기법을 사용한 트랙 나열 (Track listings with repeat() notation)

수많은 트랙을 가진 대형 그리드의 경우, 그리드 트랙 목록의 전부나 일부를 반복하기 위해 repeat() 표기법을 사용할 수 있습니다. 예를 들어 다음과 같은 그리드 정의는:

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

아래와 같이 간결하게 쓸 수 있습니다:

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* 1fr 크기의 트랙을 3번 반복합니다 */
}

반복 표기법(Repeat notation)은 트랙 목록의 일부분에만 사용할 수도 있습니다. 이 예제에서는 8열(8-column) 그리드를 생성합니다. 맨 처음 트랙은 20px이고, 그다음 6개는 1fr이 반복되는 구역이며, 마지막 트랙은 다시 20px이 됩니다.

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

반복 표기법(repeat())의 괄호 안에는 여러 개의 트랙을 묶어서 패턴으로 넣을 수도 있습니다. 이 예제에서 그리드는 10개의 트랙을 갖게 될 것입니다. 1fr 트랙과 2fr 트랙이 한 세트가 되어, 이 패턴이 5번 반복되기 때문입니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(5, 1fr 2fr);
}

암시적 그리드와 명시적 그리드 (Implicit and explicit grids)

우리가 처음 예제 그리드를 만들었을 때, 우리는 grid-template-columns 속성을 사용하여 3개의 '열(column)' 트랙을 명시적으로 정의해 주었습니다. 하지만 행(row)은 우리가 전혀 정의하지 않았음에도 콘텐츠를 다 담기 위해 필요한 만큼 그리드가 알아서 생성해 주었습니다. 여기서 우리가 직접 정의한 '열'은 명시적 그리드(explicit grid)에 속하며, 알아서 생성된 '행'은 암시적 그리드(implicit grid)의 일부가 됩니다.

  • 명시적 그리드(explicit grid): grid-template-columns 또는 grid-template-rows를 통해 개발자가 직접 크기를 지정하여 정의한 행과 열입니다.
  • 암시적 그리드(implicit grid): 콘텐츠가 개발자가 정의해둔 명시적 그리드의 바깥쪽으로 배치될 때, 콘텐츠를 담아내기 위해 추가적인 그리드 선을 그어 확장시켜 버린 부분입니다.

만약 여러분이 아이템을 정의된 그리드 밖으로 배치하거나, 아이템 수가 너무 많아서 추가적인 그리드 트랙이 필요해진 경우, 그리드는 암시적 그리드 상에 자동으로 행이나 열을 생성해 냅니다. 이 암시적 트랙들의 크기는 기본적으로 auto로 설정됩니다. 즉, 생성된 행이나 열의 크기는 내부 콘텐츠의 크기와 그리드 컨테이너 내의 남은 여유 공간의 영향을 받아 결정됩니다. 이 auto 키워드 덕분에 생성된 트랙들은 콘텐츠가 다 들어갈 수 있도록 크기를 맞추면서, 남는 공간도 나눠 가질 수 있게 됩니다.

물론, 이 암시적 그리드에서 자동으로 생성되는 트랙들의 크기 역시 우리가 제어할 수 있습니다. 이때 사용하는 속성이 바로 grid-auto-rowsgrid-auto-columns입니다.

이 예제에서 우리는 grid-auto-rows: 200px을 설정하여, 암시적 그리드에서 생성되는 모든 새로운 행 트랙들이 정확히 200px의 높이를 갖도록 강제했습니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px; /* 명시하지 않아 넘쳐흐르는 행들은 무조건 200px로 그립니다! */
}

트랙 크기 조정과 minmax (Track sizing and minmax)

명시적 그리드를 설정하거나 자동으로 생성되는 행/열의 크기를 정의할 때, 트랙에 최소한의 크기를 보장해주면서도, 그 안에 들어가는 콘텐츠 양에 맞춰 자유롭게 늘어날 수도 있게 만들고 싶을 때가 있습니다. 예를 들어, 행의 높이가 100px보다 작아지는 것은 절대 원하지 않지만, 콘텐츠의 높이가 300px까지 길어진다면 행의 높이도 거기에 맞춰 300px로 늘어나 주기를 바랄 수 있겠죠. 이럴 때를 위해 존재하는 것이 바로 minmax() 함수입니다.

이 예제에서 우리는 grid-auto-rows 속성값 안에 minmax()를 사용했습니다. grid-auto-rows: minmax(100px, auto);라고 설정함으로써, 자동으로 생성되는 행들의 높이는 최소 100px이 되고, 최대 auto가 됩니다. 최댓값을 auto로 설정하면 트랙이 자신이 가진 콘텐츠를 다 품을 수 있을 만큼(max-content 크기까지) 늘어나는 것을 허용하며, 동시에 컨테이너 내부에 남는 공간이 있다면 나눠 가질 수도 있게 됩니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto); /* 최소 100px은 유지하되, 내용물이 많으면 쭈욱 늘어나라! */
}

💡 강사의 실무 포트폴리오 팁!
블로그나 독후감 사이트의 글 목록(Card)을 만들 때 내용의 길이가 일정하지 않으면 카드의 높이가 들쭉날쭉해져서 보기가 안 좋습니다. 이럴 때 minmax()를 사용하면, 기본적으로 모든 카드가 통일된 예쁜 최소 높이를 가지면서도 글이 너무 길면 넘치지 않게 자연스럽게 늘어나게 만들 수 있습니다.


그리드 라인 (Grid lines)

우리가 그리드를 정의할 때, 우리는 '선(lines)'을 정의하는 것이 아니라 '트랙(tracks)'을 정의한다는 점에 주목해야 합니다. 하지만, 트랙을 만들고 나면 Grid는 우리에게 아이템을 배치할 때 써먹을 수 있는 번호가 매겨진 선(numbered lines)들을 제공합니다. 방금 우리가 만들었던 3열 2행짜리 그리드는 총 4개의 세로선(column lines)을 갖게 됩니다.

Diagram showing numbered grid lines.

선 번호는 문서의 쓰기 모드(writing mode)에 따라 매겨집니다. 좌에서 우로(left-to-right) 쓰는 언어 환경이라면, 1번 선은 그리드의 가장 왼쪽 가장자리가 됩니다. 반대로 우에서 좌로(right-to-left) 쓰는 언어 환경이라면, 1번 선은 그리드의 가장 오른쪽 가장자리가 됩니다. 또한 이런 숫자가 헷갈린다면 선에 직접 이름을 붙일 수도 있는데, 이에 대한 내용은 이름이 지정된 그리드 라인 사용하기 가이드에서 다루고 있습니다.

선에 맞추어 아이템 배치하기 (Positioning items against lines)

다음 예제는 선 기반 배치(line-based placement)의 기초를 보여줍니다. 아이템을 배치할 때, 우리는 '칸(track)'이 아니라 이 '선(line)'을 타겟으로 지정합니다. 우리는 이것을 선 기반 배치를 사용한 그리드 레이아웃 가이드에서 더욱 깊이 파헤쳐 볼 것입니다.

이 예제에서, 우리의 3열짜리 그리드 상에 있는 첫 번째와 두 번째 아이템은 grid-column-start, grid-column-end, grid-row-start, grid-row-end 속성을 사용하여 위치가 지정되었습니다.
왼쪽에서 오른쪽으로 흐름을 생각해보면, 첫 번째 아이템(box1)은 세로선 1번(column line 1)에서 시작하여 세로선 4번(column line 4 - 우리 그리드의 가장 오른쪽 선)까지 걸쳐 있습니다(span). 또한 가로선 1번(row line 1)에서 시작하여 가로선 3번(row line 3)에서 끝나므로, 결과적으로 두 개의 행(row tracks)에 걸치게 됩니다.

두 번째 아이템(box2)은 세로선 1번에서 시작하여 딱 한 칸(one track)만 차지합니다. 한 칸만 차지하는 것은 기본값이기 때문에 굳이 끝나는 선(end line)을 지정해 줄 필요가 없습니다. 이것 또한 가로선 3번에서 가로선 5번까지 위치하므로 두 개의 행에 걸쳐 있게 됩니다.
나머지 아이템들(box3, box4, box5)은 자기들이 들어갈 빈자리를 찾아 알아서(자동 배치) 쏙쏙 들어갈 것입니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

.box1 {
  grid-column-start: 1; /* 세로선 1번부터 */
  grid-column-end: 4;   /* 세로선 4번 전까지 쭉! */
  grid-row-start: 1;    /* 가로선 1번부터 */
  grid-row-end: 3;      /* 가로선 3번 전까지 (2줄 차지) */
}

.box2 {
  grid-column-start: 1;
  grid-row-start: 3;
  grid-row-end: 5;
}

선 배치 단축 속성 (Line-positioning shorthands)

위에서 여러 줄에 걸쳐 썼던 속성들은 하나의 단축 속성으로 묶어서 아주 간결하게 줄일 수 있습니다. 열(column) 방향은 grid-column으로, 행(row) 방향은 grid-row로 처리하면 됩니다. 다음 예제는 이전 코드와 똑같은 배치를 만들어내지만 CSS 코드는 훨씬 짧습니다. 슬래시(/) 문자 앞에 있는 값이 시작 선(start line)이고, 뒤에 있는 값이 끝나는 선(end line)입니다.

만약 해당 아이템이 딱 한 칸의 트랙만 차지한다면 끝나는 선(end value)은 아예 생략할 수 있습니다.

.box1 {
  grid-column: 1 / 4; /* 세로 1번 선부터 4번 선까지! */
  grid-row: 1 / 3;    /* 가로 1번 선부터 3번 선까지! */
}

.box2 {
  grid-column: 1;     /* 세로 1번 칸 하나만 차지합니다 */
  grid-row: 3 / 5;
}

그리드 셀 (Grid cells)

그리드 셀(grid cell)은 그리드에서 가장 작은 단위의 공간입니다. 개념상으로는 엑셀이나 표(table)의 셀(cell)과 똑같습니다. 앞선 예제에서 보았듯이, 부모가 그리드로 정의되면 자식 아이템들은 정의된 그리드의 셀 하나당 하나씩 스스로 자리를 잡습니다. 아래 이미지에서는 그리드의 첫 번째 셀이 강조 표시되어 있습니다.

The first cell of the grid highlighted


그리드 영역 (Grid areas)

아이템들은 행 방향이든 열 방향이든 여러 개의 셀(cells)에 걸쳐 공간을 차지할 수 있으며, 이렇게 만들어진 공간을 그리드 영역(grid area)이라고 부릅니다. 그리드 영역은 무조건 완벽한 직사각형(rectangular)이어야만 합니다. 예를 들어 'ㄱ' 자나 'L' 자 형태의 영역을 만드는 것은 불가능합니다. 아래 강조 표시된 그리드 영역은 두 개의 행과 두 개의 열을 아우르고 있습니다.

A grid area


거터 (Gutters)

그리드 셀들 사이의 거터(Gutters, 틈새 혹은 골목)column-gaprow-gap 속성, 또는 이 둘을 합친 단축 속성인 gap을 사용하여 만들 수 있습니다. 아래 예제에서 우리는 열(세로줄) 사이에 10px의 틈을 주고, 행(가로줄) 사이에 1em의 틈을 만들었습니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 10px;
  row-gap: 1em;
  /* 단축 속성으로 쓴다면: gap: 1em 10px; 가 됩니다 */
}

여유 공간을 유연한(fr) 트랙들에게 분배하기 전에, 가장 먼저 이 거터(gap)들이 차지하는 공간이 전체에서 미리 차감됩니다. 따라서 공간을 계산할 때 거터는 마치 고정된 크기의 일반 그리드 트랙처럼 취급됩니다. 그러나 거터(gap) 공간 안에는 그 어떤 요소도 집어넣을 수 없습니다. 선 기반 배치(line-based positioning)의 관점에서 볼 때, 거터는 투명하고 두꺼운 '선(line)' 그 자체처럼 행동합니다.


그리드 중첩하기 (Nesting grids)

그리드 아이템(자식)이 자기 자신만의 새로운 그리드 컨테이너(부모)가 될 수 있습니다. 다음 예제에서는 아까 봤던 3열짜리 그리드(이 중 두 개는 덩치가 큼)를 가져와서, 첫 번째 거대한 그리드 아이템 안에 또 다른 하위 아이템들을 추가해 보았습니다. 이 새롭게 들어간 하위 아이템들은 가장 바깥쪽의(루트) 그리드에 직접 속해있지(direct children) 않기 때문에, 첫 번째 부모의 그리드 레이아웃 규칙에 영향을 받지 않고 일반적인 문서 흐름(normal flow)을 따라 위아래로 쌓여 출력됩니다.

Nested grid in flow

Subgrid를 사용하지 않는 일반적인 중첩 (Nesting without subgrid)

만약 여기서 이 거대한 첫 번째 박스(box1)에도 display: grid를 선언해 주고 자신만의 트랙 크기를 정의해 준다면, 이 아이템 역시 어엿한 하나의 '그리드'로 변신하게 됩니다. 그러면 안에 있던 하위 아이템들은 이 새로운 규칙에 따라 그리드 상에 착착 배치되게 됩니다.

.box1 {
  grid-column: 1 / 4;
  grid-row: 1 / 3;
  display: grid; /* 나도 이제부터 그리드다! */
  grid-template-columns: repeat(3, 1fr); /* 3칸으로 쪼개라 */
}

이렇게 하면 중첩된(nested) 그리드는 자신을 감싸고 있는 바깥쪽 부모 그리드와는 아무런 관계도 맺지 않습니다. 예제에서 볼 수 있듯이, 안쪽 그리드는 바깥쪽 부모의 gap 속성을 물려받지(inherit) 않으며, 안쪽 그리드의 세로선들이 바깥쪽 그리드의 세로선들과 딱 맞아떨어지지도 않습니다.

서브그리드 (Subgrid)

이러한 한계를 극복하기 위해, 우리는 일반적인 중첩 그리드 외에도 서브그리드(subgrid)라는 것을 만들 수 있습니다. subgrid 값을 사용하면 부모 그리드의 트랙 크기와 선(라인)을 그대로 물려받아서 사용하는 중첩된 그리드를 만들 수 있습니다!

이 마법 같은 기능을 사용하려면, 위의 중첩 그리드 예제에서 선언했던 grid-template-columns: repeat(3, 1fr) 부분을 grid-template-columns: subgrid로만 슬쩍 바꿔주면 됩니다. 그러면 중첩된 그리드는 아이템을 배치할 때 부모 그리드가 그려둔 트랙 선을 그대로 이어받아 사용하게 됩니다. (즉, 선이 완벽하게 일치하게 됩니다!)

.box1 {
  grid-column: 1 / 4;
  grid-row: 1 / 3;
  display: grid;
  grid-template-columns: subgrid; /* 부모가 그어놓은 선을 그대로 가져다 씁니다! */
}

z-index로 아이템 겹치기 (Layering items with z-index)

그리드에서는 여러 아이템들이 같은 셀(cell) 공간을 차지하는 것이 가능합니다. 그리고 이렇게 겹치는(overlapping) 아이템들이 발생했을 때, 우리는 z-index 속성을 사용하여 누가 앞으로 오고 누가 뒤로 숨을지 스태킹 순서(stacking order)를 제어할 수 있습니다.

z-index 없이 겹칠 때 (Overlapping without z-index)

선 번호(line number)를 통해 아이템을 배치했던 예제로 다시 돌아가서 코드를 살짝 수정해 두 아이템의 영역이 서로 겹치게 만들어 보겠습니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

.box1 {
  grid-column: 1 / 4;
  grid-row: 1 / 3; /* 세로로 1, 2번째 줄 차지 */
}

.box2 {
  grid-column: 1;
  grid-row: 2 / 4; /* 세로로 2, 3번째 줄 차지 -> 2번째 줄에서 box1과 겹침! */
}

결과를 보면 box2box1 위로 올라타서(overlapping) 표시되는 것을 볼 수 있습니다. HTML 소스 코드상에서 box2box1보다 나중에 쓰였기 때문(source order)에 위로 덮어쓰게 되는 것입니다.

순서 제어하기 (Controlling the order)

우리는 아이템들이 쌓이는(stack) 순서를 z-index 속성으로 자유자재로 통제할 수 있습니다. (마치 position: absolute를 썼을 때처럼 말이죠!) 만약 box2box1보다 더 낮은 z-index 숫자를 준다면, box2는 스택의 아래쪽으로 깔려 box1 뒤로 숨게 될 것입니다.

.box1 {
  grid-column: 1 / 4;
  grid-row: 1 / 3;
  z-index: 2; /* 내가 더 번호가 높으니 내가 위로 갈게! */
}

.box2 {
  grid-column: 1;
  grid-row: 2 / 4;
  z-index: 1; /* 내가 번호가 낮으니 밑으로 숨을게.. */
}

다음 단계 (Next steps)

이 개요 문서에서는 그리드 레이아웃이 가진 무궁무진한 가능성들을 아주 빠르게 훑어보았습니다. 위에 제시된 코드 예제들을 이리저리 수정하며 놀아 보시고, 그다음에는 이 명세서가 다른 레이아웃 방식(Flexbox 등)과 어떤 관계를 맺고 있는지에 대한 가이드로 넘어가 보시기를 권합니다. 거기서부터 우리는 CSS 그리드 레이아웃의 디테일들을 본격적으로 파헤치게 될 것입니다.


MDN 개선에 참여하기 (Help improve MDN)

이 페이지가 도움이 되셨나요?

기여하는 방법 알아보기 (Learn how to contribute)

이 페이지는 MDN 기여자들에 의해 2025년 12월 16일에 마지막으로 수정되었습니다 (MDN contributors).

profile
프론트에_가까운_풀스택_개발자

0개의 댓글