Skip to content
This page has been auto-translated and may contain errors.View in English

Grid

docs.scrimba.com

맨 위에 헤더, 왼쪽에 사이드바, 중앙에 메인 콘텐츠 영역, 하단에 푸터가 있는 페이지가 있다고 생각해 보세요. 컨테이너를 겹겹이 중첩시키고 각각을 제자리에 밀어내는 방식으로 배치할 수 있지만, 레이아웃을 변경해야 하는 날이 오면 대부분 제대로 작동하지 않습니다. CSS grid는 정확히 이런 문제를 해결하기 위해 만들어졌습니다. 행과 열을 동시에 페이지를 배치하는 것입니다. 레이아웃을 트랙 집합으로 설명할 수 있으면, 래퍼와 float에서 반복적인 작업의 대부분이 사라집니다.

Grid 컨테이너

display: grid를 요소에 지정하여 grid로 변환합니다. 그 요소는 **grid 컨테이너**가 되고, 직접 자식들은 사용자가 정의하는 grid에 맞추는 항목이 됩니다. display: grid만으로는 많이 하지 못하므로, 원하는 열과 행의 개수와 각각의 크기를 지정해야 합니다.

grid-template-columns로 열을 설명하고 grid-template-rows로 행을 설명합니다. 목록의 각 값은 하나의 트랙이고, 트랙은 하나의 열 또는 행입니다.

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;   /* 두 개의 열: 고정된 열, 그 다음 나머지 */
  grid-template-rows: 80px 400px;     /* 두 개의 행: 짧은 행, 그 다음 높은 행 */
}

요소에 display: grid를 설정하면 **grid 컨테이너**가 되고, 직접 자식들은 사용자가 정의하는 grid에 배치되는 grid 항목이 됩니다. 이는 한 번에 하나의 축을 따라 항목을 배치하는 flexbox의 2차원 대응물입니다. Flexbox는 "이 행(또는 열)의 항목들이 공간을 어떻게 공유해야 하는가?"를 묻고, grid는 "이 항목들이 행과 열의 집합에서 어디에 앉아야 하는가?"를 묻습니다.

grid-template-columnsgrid-template-rows로 트랙을 정의합니다. 각 값은 하나의 트랙(열 또는 행)이고, 값들은 단위를 혼합할 수 있습니다. 고정 길이, 백분율, 또는 다음 섹션에서 만나는 유연한 fr 단위입니다.

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;   /* 고정 사이드바, 유연한 메인 열 */
  grid-template-rows: auto 1fr auto;  /* 헤더는 콘텐츠에 맞춤, 메인은 채움, 푸터는 콘텐츠에 맞춤 */
}

display: grid는 요소에 **grid 형식화 컨텍스트**를 설정합니다. 요소는 grid 컨테이너가 되고, 직접 자식들은 grid 항목이 되며, 이전에 해당 자식들을 지배하던 normal-flow 규칙이 더 이상 적용되지 않습니다. 텍스트 노드는 익명 항목으로 래핑되고, floatvertical-align 같은 속성들은 항목에 더 이상 영향을 미치지 않습니다. 이제 배치는 grid의 일입니다.

flexbox와의 차이는 차원성이며, 올바르게 결정하는 것이 첫 번째 선택입니다. Flexbox는 1차원입니다. 주 축을 따라 항목을 배분하고 결과로서 래핑되지만, 교차 축에서 일치하는 grid에 콘텐츠를 정렬하지 않습니다. Grid는 2차원입니다. 행과 열을 함께 정의하므로 항목의 행 위치와 열 위치가 독립적으로 설정되고 항목들이 두 축 모두에 정렬됩니다. grid-template-columnsgrid-template-rows로 명시적 트랙을 정의하고, 각 값은 하나의 트랙을 생성합니다.

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;   /* 두 개의 명시적 열 트랙 */
  grid-template-rows: auto 1fr auto;  /* 콘텐츠, 채움, 콘텐츠 */
}

auto 키워드는 트랙 크기를 콘텐츠에 맞춥니다. 1fr은 남은 공간을 흡수하며, 이는 다음 섹션이 구축하는 메커니즘입니다.

JunoGrid 컨테이너 요소에 display: grid를 추가하면 grid 컨테이너가 되고, 직접 자식들이 항목으로 내부에 앉습니다. 그 다음 grid-template-columnsgrid-template-rows로 원하는 열과 행의 개수를 지정합니다. 트랙당 하나의 값입니다. 해당 트랙을 정의하기 전까지는 아무것도 정렬되지 않으므로, 항상 첫 번째 단계입니다.
JunoGrid 컨테이너 Flexbox는 한 번에 한 축을 따라 작동합니다. Grid는 행과 열을 함께 작동하므로 페이지 레이아웃이 grid에서 더 자연스럽게 느껴집니다. display: grid를 설정한 다음 grid-template-columnsgrid-template-rows에 트랙을 나열합니다. 2차원 배열로 항목을 배치할 때는 grid를 사용하고, 한 행 또는 한 열을 정렬할 때는 flexbox를 사용합니다.
JunoGrid 컨테이너display: grid는 grid 형식화 컨텍스트를 만들므로 자식들이 normal flow를 따르지 않고 float과 vertical-align은 조용히 그들에 대해 작동을 멈춥니다. Flexbox와의 실제 차이는 차원성입니다. Flex는 한 축을 따라 배분하고, grid는 두 축 모두에 동시에 배치합니다. 행과 열 위치가 모두 의미가 있을 때는 grid를 선택하고, 하나의 축만 의미가 있을 때는 flex를 선택합니다.

유연한 트랙

고정 픽셀 열은 괜찮지만, 대부분의 레이아웃은 공간을 균등하게 공유하고 화면에 따라 커지는 열을 원합니다. 그것이 **fr 단위**가 하는 일입니다. 하나의 fr은 남은 공간의 한 몫을 의미하므로, 각각 1fr인 세 개의 열은 컨테이너의 1/3씩 차지합니다.

css
.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;   /* 세 개의 같은 크기 열 */
}

1fr을 세 번 입력하는 것은 지루하므로, repeat()로 자동으로 작성할 수 있습니다. 그리고 gap은 트랙 사이의 공간을 설정하므로 모든 항목에 마진을 설정할 필요가 없습니다.

css
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* 같은 세 개의 열 */
  gap: 16px;                               /* 행과 열 사이의 공간 */
}

fr 단위는 고정 크기와 간격이 제거된 후 컨테이너의 여유 공간의 몫을 측정합니다. 각각 1fr인 세 개의 열은 같은 1/3씩 얻습니다. 2fr 1fr 쌍은 공간을 2:1로 분할합니다. fr이 남은 것을 분할하기 때문에 열은 컨테이너가 커지거나 줄어들 때도 비례 유지합니다. 고정 길이는 그럴 수 없습니다.

두 가지 도우미가 트랙 목록을 읽기 쉽게 만듭니다. repeat(3, 1fr)1fr 1fr 1fr로 확장되고, gap은 하나의 속성으로 거터를 설정합니다. (row-gapcolumn-gap으로 다르게 하려면 사용).

css
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* 세 개의 같은 크기 열 */
  gap: 16px;                               /* 16px 거터, 행과 열 */
}

거터는 항목의 마진이 아닌 gap으로 설정됩니다. gap은 트랙 사이에만 적용되고 외부 가장자리에는 적용되지 않으므로, grid는 컨테이너에 밀착되면서 항목은 균등하게 간격이 유지됩니다.

fr 단위는 **유연한 길이**입니다. 컨테이너의 여유 공간(고정 트랙 크기, 콘텐츠 크기의 트랙, 간격이 해결된 후 남은 공간)의 분수를 나타냅니다. 2fr 1fr 1fr 트랙 목록은 첫 번째 열에 여유 공간의 절반을, 다른 두 열에 각각 1/4을 줍니다. 미묘한 점은 fr여유 공간을 배분하지, 전체 너비가 아니라는 것입니다. 따라서 넓은 콘텐츠를 담는 트랙은 minmax()로 캡하지 않으면 fr 몫을 초과할 수 있으며, 이는 마지막 섹션에서 나옵니다.

repeat()은 트랙 실행을 작성하는 간편한 방법입니다. repeat(3, 1fr)1fr 1fr 1fr이고, 조합 가능하므로 repeat(2, 200px 1fr)은 4개 트랙을 낳습니다. gap(현대식 이름은 grid-gap)은 트랙 사이의 거터만 설정하고, grid 외부를 절대로 설정하지 않으므로 컨테이너 자체의 padding과 싸우지 않습니다.

css
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* 세 개의 같은 크기 열 */
  gap: 16px 24px;                          /* 16px 행 간격, 24px 열 간격 */
}

두 값 gap을 주목합니다. 행 간격 먼저, 그 다음 열 간격. 단일 값은 둘 다에 적용됩니다.

Juno유연한 트랙 하나의 fr은 남은 공간의 한 몫이므로, 1fr 1fr 1fr은 세 개의 같은 크기 열을 제공합니다. repeat(3, 1fr)을 사용하여 같은 값을 반복해서 입력하지 마세요. 그리고 트랙 사이의 공간에 gap을 사용합니다. fr이 제 머리에 들어왔을 때, 절대 맞지 않는 백분율을 더 이상 찾지 않아도 됩니다.
Juno유연한 트랙fr은 컨테이너의 여유 공간을 분할하므로, 비례적 열은 페이지 크기 변경 시에도 비례 유지됩니다. repeat()에 의존하여 트랙 목록을 짧게 유지하고 항목별 마진 대신 gap을 거터에 사용합니다. gap은 트랙 사이에만 있고, 외부 가장자리에는 없으며, 이는 보통 정확히 원하는 것입니다.
Juno유연한 트랙fr은 전체 너비가 아닌 여유 공간을 분할하므로, 넓은 콘텐츠를 담는 트랙은 minmax()로 캡하기 전까지 몫을 초과할 수 있습니다. repeat()은 조합 가능하므로, repeat(2, 200px 1fr)은 4개 트랙입니다. 그리고 두 값 gap은 행 간격 먼저, 그 다음 열 간격으로 읽히며, 이는 시계 방향 단축형을 가정하는 사람들을 혼동시킵니다.

항목 배치

기본적으로 각 항목은 다음 여유 셀로 떨어지며, 셀당 하나씩, 순서대로 떨어집니다. 항목이 하나 이상의 셀을 차지하게 하려면 grid-columngrid-row로 지정합니다. 트랙 사이의 선은 1부터 시작해서 번호가 매겨지므로, grid-column: 1 / 3은 "선 1에서 시작하여 선 3에서 끝남"을 의미하며, 두 개의 열을 커버합니다.

css
.featured {
  grid-column: 1 / 3;   /* 열 선 1에서 선 3까지, 두 개 열 너비 */
}

선을 세지 않으려면, span은 항목이 착지한 위치에서 몇 개의 셀을 커버할지 말합니다.

css
.featured {
  grid-column: span 2;   /* 두 개의 열을 커버, 이 항목이 앉는 위치에서 시작 */
}

Grid 배치는 **grid 선**으로 설명됩니다. 트랙 사이 및 주변에 앉는 번호가 매겨진 선입니다. 3열 grid에는 4개의 열 선 1부터 4까지 있습니다. grid-column: 1 / 3은 항목을 선 1에서 선 3까지 배치하므로 처음 두 개의 열을 확장합니다. grid-row는 수직으로 같은 작업을 합니다. span 키워드는 선 세기를 피합니다. grid-column: span 2는 항목이 배치된 위치에서 두 개의 열을 커버합니다.

전체 페이지 레이아웃의 경우, 선 번호를 세는 것보다 영역 이름을 지정하는 것이 더 읽기 좋습니다. grid-template-areas는 레이아웃을 명명된 셀 집합으로 그린 다음 각 항목을 이름에 할당할 수 있습니다.

css
.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main";     /* 사이드바는 이름을 반복하여 두 행을 확장 */
}

.page > header { grid-area: header; }
.page > aside  { grid-area: sidebar; }
.page > main   { grid-area: main; }

배치는 **grid 선**에서 실행됩니다. 모든 트랙 주변의 번호가 매겨진 경계입니다. (n 트랙 축은 n + 1 선을 가집니다). grid-column: 1 / 3은 시작과 끝 열 선을 설정하여 그 사이의 트랙을 확장합니다. grid-column: span 2는 시작을 고정하지 않고 span을 설정하며, 자동 배치 알고리즘이 배치되는 위치를 선택하게 합니다. 음수 선 번호는 끝에서 세므로, grid-column: 1 / -1은 열 개수와 관계없이 항상 전체 너비를 확장합니다. 이는 전폭 행을 작성하는 내구성 있는 방법입니다.

grid-template-areas는 셀의 이름을 지정하므로 선 번호가 아닌 이름으로 항목을 배치합니다. 각 문자열은 행이고, 각 토큰은 셀이며, 토큰을 셀에 반복하면 한 항목이 확장됩니다. 공백으로 서식이 지정된 블록은 레이아웃의 읽기 쉬운 다이어그램으로 두 배입니다.

css
.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main";     /* 사이드바는 열 1의 두 행을 차지 */
}

.page > aside { grid-area: sidebar; }

두 가지 규칙이 명확성을 유지합니다. 모든 행 문자열은 같은 수의 셀을 가져야 하고, 하나의 이름에 대한 셀은 단색 직사각형을 형성해야 하거나, 선언은 유효하지 않고 무시됩니다. . 토큰은 의도적으로 비워두고 싶은 빈 셀을 표시합니다.

Juno항목 배치 항목은 기본적으로 셀당 하나씩 채워지며, grid-column 또는 grid-row로 하나를 셀에 걸쳐 늘입니다. 선 번호는 1부터 시작하므로, grid-column: 1 / 3은 두 개의 열을 커버합니다. 또는 선을 세지 않으려면 span 2를 사용합니다. 단일 영역의 이름도 지정하기 전에 대부분의 레이아웃을 구축하기에는 충분합니다.
Juno항목 배치 grid 선으로 항목을 배치합니다. grid-column: 1 / 3은 두 개의 열을 확장하고, span 2는 고정 시작에서 세지 않고 합니다. 전체 페이지의 경우, grid-template-areas는 영역의 이름을 지정하고 한눈에 레이아웃을 읽을 수 있으므로, 선 번호를 손으로 추적하는 것보다 낫습니다. 이름을 셀에 반복하면 해당 영역은 확장됩니다.
Juno항목 배치 선은 음수일 수 있으므로, grid-column: 1 / -1은 열 개수와 무관하게 전체 너비를 확장합니다. 이는 신뢰할 수 있는 전폭 트릭입니다. grid-template-areas에서 모든 행 문자열은 동일한 셀이 필요하고 각 명명된 영역은 단색 직사각형이어야 하거나, 전체 선언은 삭제됩니다. . 토큰을 사용하여 셀을 의도적으로 비워둡니다.

미디어 쿼리 없는 반응형 그리드

카드 행은 넓은 화면에서 3개씩, 태블릿에서 2개씩, 휴대폰에서 1개씩 표시되어야 합니다. Grid만으로 할 수 있습니다. 중단점을 작성할 필요가 없습니다. 비결은 한 줄입니다.

css
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

안에서 밖으로 읽으세요. minmax(200px, 1fr)은 각 열이 최소 200px이고 최대 공간의 한 몫을 의미합니다. auto-fit은 그 열이 컨테이너 너비에 맞는 만큼 많이 맞춥니다. 넓은 화면, 더 많은 열이 맞음. 좁은 화면, 더 적은 열이 맞고, 카드는 자동으로 다시 흐릅니다.

미디어 쿼리 하나 없이 카드를 다시 흐르게 하는 패턴은 repeat(auto-fit, minmax(200px, 1fr))입니다. 각 부분은 한 가지 일을 합니다. minmax(200px, 1fr)200px보다 작지 않고 fr 몫보다 크지 않은 트랙을 정의합니다. auto-fit은 현재 너비를 따라 맞는 만큼 해당 트랙을 반복합니다. 따라서 열 개수는 고정 중단점이 아닌 컨테이너에 반응합니다.

css
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

200px 하한은 실제 제어입니다. 그리드가 더 적은 열로 떨어지기 전에 카드가 가져야 할 수 있는 가장 좁은 너비입니다. 이는 반응형 디자인의 유동 기술과 자연스럽게 페어링되며, 보통 카드 그리드에 대해 작성할 것 같은 미디어 쿼리를 대체합니다.

repeat(auto-fit, minmax(200px, 1fr))은 표준 반응형 그리드 관용어이며, 각 부분은 제 자리를 얻습니다. minmax(min, max)는 상한과 하한이 있는 트랙을 정의합니다. minmax(200px, 1fr)200px 아래로 줄어들지 않고 여유 공간 몫을 넘어서 커지지 않습니다. 200px 하한은 다시 흐르는 임계값, 그리드가 열을 얻거나 잃는 너비입니다.

auto-fitauto-fill 중 선택하는 것은 알 가치가 있는 부분입니다. 둘 다 minmax() 트랙이 컨테이너에 맞는 개수를 계산합니다. auto-fill은 남은 빈 트랙을 grid에 유지하므로, 반쯤 비은 카드 행은 열 너비로 유지됩니다. auto-fit은 그 빈 트랙을 0 너비로 축소하므로, 현재 항목은 행을 채우도록 확장됩니다.

css
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));   /* 항목이 채우도록 확장 */
  gap: 16px;
}

하나의 가장자리를 보세요. minmax(200px, 1fr)200px 더하기 간격보다 좁은 컨테이너에서 오버플로우할 수 있습니다. 하한이 hard 최솟값이기 때문입니다. minmax(min(200px, 100%), 1fr)은 매우 작은 화면에서 하한을 컨테이너 너비로 떨어지도록 함으로써 이를 방지합니다. 기기에 걸쳐 하한 크기를 신뢰할 수 있으려면, 크기 지정 단위가 길이 단위가 어떻게 해결되는지 다룹니다.

Juno미디어 쿼리 없는 반응형 그리드repeat(auto-fit, minmax(200px, 1fr))은 카드를 자동으로 다시 흐르게 하며, 중단점이 필요하지 않습니다. 각 열은 최소 200px이고 최대 공간의 한 몫입니다. auto-fit은 맞는 만큼 많이 팩합니다. 200px을 변경하면 한 줄에 앉는 카드 개수를 변경합니다.
Juno미디어 쿼리 없는 반응형 그리드 한 줄, repeat(auto-fit, minmax(200px, 1fr)), 카드 그리드 미디어 쿼리의 스택을 대체합니다. 200px 하한은 지렛대입니다. 카드가 grid가 열을 떨어뜨리기 전에 얼마나 좁아질 수 있는지를 결정합니다. 정말 다시 흐르는 카드 그리드인 무엇이든에 대해 중단점을 작성하기 전에 이것을 찾습니다.
Juno미디어 쿼리 없는 반응형 그리드auto-fit은 빈 트랙을 축소하므로 현재 항목이 채우도록 확장됩니다. auto-fill은 빈 트랙을 유지하고 간격을 남기므로, 그들 사이의 전체 차이입니다. 오버플로우 경우를 지켜봅니다. Hard 200px 하한은 매우 좁은 컨테이너에서 유출될 수 있으므로, minmax(min(200px, 100%), 1fr)이 더 안전한 하한입니다. 하한은 다시 흐르는 점을 설정하므로, 감각적인 가장 작은 카드를 염두에 두고 선택합니다.

명시적 및 암시적 그리드

지금까지 모든 것이 **명시적 그리드**를 정의합니다. grid-template-columnsgrid-template-rows에서 이름을 지정하는 트랙입니다. 항목이 정의된 그리드 외부에 착지할 때, 브라우저는 항목을 보유하는 트랙을 만들고, 이들은 **암시적 그리드**를 형성합니다. 3열, 1행 명시적 그리드에 4번째 항목을 추가하면 새로 암시적으로 생성된 두 번째 행이 시작됩니다. 암시적 트랙은 기본적으로 auto 크기이므로, auto 행은 그 콘텐츠만큼 높습니다. 다르게 말할 때까지입니다.

grid-auto-rows는 그 암시적 행의 크기를 설정합니다. (grid-auto-columns는 암시적 열) 그래서 행 개수를 예측할 수 없는 카드 그리드도 짝수 행을 얻습니다.

css
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* 명시적: 3열 */
  grid-auto-rows: 240px;                   /* 암시적 행은 각각 240px */
  gap: 16px;
}

정렬은 그 다음 항목과 트랙이 그 셀 내에서 어디에 앉는지 결정합니다. justify-items는 행(inline) 축을 따라 항목을 정렬하고, align-items는 열(block) 축을 따라 정렬하며, 각각은 start, end, center, 또는 stretch(기본값, 셀을 채움)를 받습니다. place-items는 둘 다를 위한 단축형이며, block 축 먼저입니다.

css
.gallery {
  place-items: center;   /* align-items와 justify-items, 둘 다 중앙 정렬 */
}

minmax()는 또한 콘텐츠 키워드 min-contentmax-content를 가집니다. min-content는 오버플로우 없이 트랙이 가질 수 있는 가장 작은 것입니다. (대략 가장 긴 나눌 수 없는 단어). max-content는 콘텐츠가 아무것도 래핑을 강제하지 않을 때 원하는 크기입니다. minmax(min-content, max-content) 같은 트랙은 그 범위 내에서 콘텐츠 크기입니다. 그리고 subgrid는 중첩된 그리드가 부모의 트랙 선을 상속하도록 합니다. 따라서 자식 그리드의 열은 자신의 것을 정의하는 대신 외부 그리드와 정렬됩니다.

Grid 대 flex 결정에 대해, 깔끔한 규칙은 이것입니다. 하나의 축에서 콘텐츠를 배열하고 결과로서 래핑하게 하려면 flexbox를 사용합니다. 네비게이션 바, 태그 행, 도구 모음. 행과 열에 콘텐츠를 배치하려면 두 축 모두에 정렬되어야 하며, grid를 사용합니다. 페이지 shell, 카드 갤러리, 정렬된 레이블과 필드가 있는 양식. 그들은 잘 조합되므로, grid 셀은 종종 flex 컨테이너를 보유하고, 그 조합은 구축할 대부분의 레이아웃을 다룹니다.

Juno명시적 및 암시적 그리드 선언하는 트랙은 명시적 그리드입니다. 오버플로우 항목을 보유하기 위해 브라우저가 추가하는 것은 암시적 그리드이며, 그 추가 트랙은 grid-auto-rows 또는 grid-auto-columns이 다르게 말할 때까지 auto 크기입니다. 정렬은 justify-itemsalign-items에 있으며, place-items는 단축형이고 stretch는 기본값입니다. 결정은 래핑 있는 하나의 축은 flexbox, 정렬되어야 하는 두 축은 grid를 의미하며, 그들은 행복하게 중첩됩니다.