세 줄로 만드는 grid
컨테이너에 display: grid를 주고 grid-template-columns로 열을 나열하세요. 자식은 순서대로(영어에서는 왼쪽에서 오른쪽으로) 칸을 채우고, 열이 차면 새 행이 시작돼요.
항목 일곱 개, 열 세 개예요. 꽉 찬 행 두 개와, 첫 번째 열에 항목 7이 있는 세 번째 행이 생겨요. 모든 열의 너비가 같고 한 행의 모든 항목의 높이가 같아서 가장자리가 두 방향으로 맞춰져요. 이게 grid가 flexbox에 더하는 거예요.
Grid 플레이그라운드
아무 grid-template-columns 값이나 입력하거나 프리셋을 클릭하세요. 표시 창은 브라우저가 계산한 열 너비(getComputedStyle에서 가져와요)와 항목에 필요했던 행 수를 보여 줘요.
볼 만한 것들이에요. 1fr 2fr은 두 번째 열을 정확히 첫 번째의 두 배로 만들어요. 200px 1fr은 200px을 유지하고 나머지를 두 번째 열에 줘요. auto 1fr auto는 바깥 열을 콘텐츠 크기로 맞춰요. repeat(4, 100px)는 유연한 게 없어서 끝에 빈 공간을 남겨요. 1fr 2 같은 잘못된 값은 무시되고, grid는 마지막으로 유효했던 값을 유지해요.
fr 단위
fr은 "빈 공간의 한 몫"이라는 뜻이에요. 브라우저는 먼저 고정 열(px, rem, %, auto 콘텐츠)과 간격을 빼고, 남은 공간을 fr 열에 숫자대로 나눠요.
600px 컨테이너, 간격 없음에서 grid-template-columns | 열 너비 |
|---|---|
1fr 1fr 1fr | 200, 200, 200 |
1fr 2fr | 200, 400 |
100px 1fr 1fr | 100, 250, 250 |
1fr 50% | 300, 300 |
fr은 %와 달라요. 퍼센트에 간격을 더하면 100%를 넘어서 넘칠 수 있지만, fr 열은 항상 간격을 뺀 나머지만 나눠요.
repeat(), minmax(), 미디어 쿼리 없는 반응형 grid
repeat(4, 1fr)는 1fr 1fr 1fr 1fr이에요. minmax(120px, 1fr)는 120px보다 좁아지지 않고 몫을 가져가도록 커지는 열이에요. 이 둘을 개수 대신 auto-fill이나 auto-fit과 함께 쓰면 grid가 들어가는 만큼 열을 만들어요.
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 16px;
}
이 선언 하나로 컨테이너에 들어가는 만큼 최소 180px 열이 생겨요. 넓은 화면에서는 여러 개, 휴대폰에서는 하나이고, 미디어 쿼리가 필요 없어요. auto-fill과 auto-fit의 차이는 항목이 열보다 적을 때 드러나요.
컨테이너에는 100px 열이 다섯 개 들어가요. auto-fill은 다섯 개를 모두 유지해서 A, B, C가 각각 112px이고 빈 열 두 개가 남아요. auto-fit은 빈 열을 접어서 세 항목이 각각 약 187px로 늘어나요.
항목 배치: grid-column과 grid-row
grid 선은 시작 가장자리에서 1부터 번호가 매겨져요. grid-column: 1 / 3은 "1번 선에서 3번 선까지", 즉 두 열이에요. span 2는 "놓인 곳에서부터 두 열"이고, -1은 마지막 선이에요.
어두운 항목은 첫 행 전체를 채워요. 파란 항목은 2 x 2 블록을, 주황 항목은 두 행을 덮어요. 항목 a와 b는 알아서 남은 칸을 채워요. grid는 배치할 수 있는 모든 항목을 다음 빈칸에 넣어요. grid-auto-rows: 60px는 grid-template-rows로 선언하지 않은 행의 높이를 정해요.
grid-template-areas: 레이아웃 부분에 이름 붙이기
페이지 레이아웃에서는 영역에 이름을 붙이고 텍스트로 그려요. 문자열 하나가 행이고, 단어 하나가 칸이며, 항목은 grid-area로 영역에 들어가요.
헤더와 푸터는 이름이 자기 행의 두 칸을 모두 채워서 두 열을 차지해요. 가운데 행은 1fr이라 280px 중 남은 높이를 모두 가져가요. 휴대폰에서 모든 것을 쌓으려면 미디어 쿼리에서 영역을 한 열로 다시 그리기만 하면 돼요. grid-template-columns: 1fr와 함께 grid-template-areas: "header" "side" "main" "footer"예요. 미디어 쿼리 페이지에서 이 패턴을 보여 줘요.
칸 안에서 정렬하기
grid 항목은 기본적으로 칸을 채우도록 늘어나요. 다음 속성들은 칸 안에서 항목을 움직여요.
| 속성 | 주는 곳 | 움직이는 것 |
|---|---|---|
justify-items | 컨테이너 | 모든 항목을 행 방향(인라인 축)으로 |
align-items | 컨테이너 | 모든 항목을 위아래(블록 축)로 |
place-items | 컨테이너 | 단축 속성: place-items: center는 양쪽으로 가운데 정렬 |
justify-self / align-self | 항목 | 항목 하나 |
justify-content / align-content | 컨테이너 | grid가 컨테이너보다 작을 때 트랙 묶음 전체 |
display: grid; place-items: center;가 상자 안에서 자식 하나를 가운데 정렬하는 가장 짧은 방법이에요.
grid와 flexbox
grid는 2차원이에요. 열(과 행)을 정하면 콘텐츠가 그걸 채워서, 갤러리의 모든 카드가 마지막 행에서도 같은 너비를 가져요. flexbox는 1차원이에요. 항목이 한 줄을 따라 콘텐츠로 크기가 정해져요. 둘은 잘 어울려요. 페이지와 카드 갤러리에는 grid를, 각 카드 안의 헤더 행에는 flexbox를 쓰세요. 나머지 절반은 flexbox 페이지에서 다뤄요.
순서와 접근성
grid-template-areas, grid-row, grid-column, order는 항목을 어디에든 놓을 수 있지만, 스크린 리더와 Tab 키는 여전히 HTML 순서를 따라요. 소스 순서를 의미 있게 유지하고(헤더, 내비게이션, 메인, 푸터) grid는 그걸 배치하는 데 쓰세요. 말이 안 되는 HTML 순서를 고치는 데 쓰지 마세요.
자주 하는 실수
- 항목에
display: grid주기. 부모에 줘야 해요. 직계 자식만 grid 항목이에요. - 간격과 함께 퍼센트 쓰기.
grid-template-columns: 50% 50%에gap: 16px을 더하면 16px 넘쳐요.1fr 1fr을 쓰세요. auto-fit을 원했는데auto-fill쓰기. 항목이 적으면auto-fill은 빈 열을 남겨요. 항목을 늘리려면auto-fit으로 바꾸세요.- 자기 몫보다 커지는
1fr열.1fr열은 가장 긴 콘텐츠(긴 URL, 넓은 이미지)보다 작게 줄어들지 않아요.minmax(0, 1fr)를 쓰면 줄어들 수 있어요. - 직사각형이 아닌 영역 문자열. 이름 붙은 모든 영역은 직사각형이어야 하고, 모든 행 문자열의 칸 수가 같아야 해요. 그렇지 않으면
grid-template-areas선언 전체가 무시돼요. - 선 번호가 1부터 시작한다는 걸 잊기. 열 세 개에는 선이 네 개 있어요.
1 / 4나1 / -1이 세 열 모두를 차지해요.
자주 묻는 질문
CSS grid란 무엇인가요?
요소를 행과 열에 동시에 배치하는 레이아웃 시스템이에요. 컨테이너에 display: grid를 주고, grid-template-columns로 열을(원하면 행도) 정의하면, 직계 자식이 순서대로 칸을 채워요.
CSS grid에서 1fr은 무슨 뜻인가요?
fr은 grid 컨테이너의 빈 공간을 나눈 몫이에요. grid-template-columns: 1fr 1fr 1fr은 같은 너비의 열 세 개를 만들고, 1fr 2fr은 두 번째 열을 첫 번째의 두 배로 만들어요. 고정 크기와 간격을 먼저 빼고, 남은 공간을 fr 열이 나눠 가져요.
auto-fill과 auto-fit은 무엇이 다른가요?
둘 다 들어가는 만큼 열을 만들어요. auto-fill은 빈 열을 유지해서 항목이 적으면 좁게 남고 행 끝에 빈 공간이 생겨요. auto-fit은 빈 열을 접어서 항목이 행을 채우도록 늘어나요. 행을 채울 만큼 항목이 있으면 둘은 똑같아 보여요.
grid 항목이 두 열을 차지하게 하려면 어떻게 하나요?
항목에 grid-column: span 2를 주거나, 시작선과 끝선을 지정하세요. grid-column: 1 / 3은 1열과 2열을 덮어요. -1이 마지막 선이라서 grid-column: 1 / -1은 전체 너비를 차지해요.
flexbox 대신 grid는 언제 써야 하나요?
행과 열이 서로 맞춰져야 할 때 grid를 쓰세요. 카드 갤러리, 레이블이 정렬된 폼, 헤더, 사이드바, 푸터가 있는 페이지예요. 내비게이션 바처럼 항목이 콘텐츠로 크기가 정해지는 한 행이나 한 열에는 flexbox를 쓰세요.
grid-gap과 gap은 같은가요?
네. grid-gap, grid-row-gap, grid-column-gap은 옛 이름이에요. 브라우저가 여전히 별칭으로 받지만, flexbox에서도 동작하는 gap, row-gap, column-gap으로 쓰세요.