7분만에 알아보는 CSS Grid
이제는 끝내야지 Grid
지난 시간 flex에 이어 이번 시간에는CSS Grid에 대해서 알아보도록 하겠습니다.
CSS Grid?
flex의 경우, 1차원(행과 열)로만 아이템들을 배치할 수 있었습니다. 그러한 이유로 2차원으로 아이템을 배치할 때 여러 개의 flex를 조합해서 사용했었습니다. 이에 반해 CSS grid는 2차원으로 아이템을 배치할 수 있습니다. 그로인해 작성해야 하는 코드가 효율적이고, 단순하게 작성할 수 있는데 이에 대해서 알아보도록 하겠습니다.
Grid 만들기
<style>
.container {
display: grid;
}
</style>
<div class="container">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
<div class="box">D</div>
<div class="box">E</div>
<div class="box">F</div>
</div>grid를 만드는 방식은 flex와 비슷합니다. flex와 마찬가지로 grid 내부에 들어갈 아이템들의 부모 요소에 display: grid 를 적용하면 자식 요소들이 grid에 영향을 받게 됩니다.
코드를 실행하면 위와 각 자식 요소가 하나의 block을 차지하게 되는데, 이것은 grid의 기본 설정으로 column과 row를 아무것도 설정해주지 않아서 그렇습니다. 그럼 이제 본격적으로 2차원 layout을 설정해보도록 하겠습니다.
Column, Row 설정하기
grid-template-columns
column을 설정할 때에는 grid-template-columns 속성을 사용합니다.
.container {
display: grid;
grid-template-columns: 100px 200px 300px;
}예를 들어, grid-template-columns: 100px 200px 300px 을 적용하면 하나의 row에서 100px 칼럼 하나, 200px 칼럼 하나, 300px 칼럼 하나를 만들고 grid 내부의 아이템을 아래와 같이 채우게 됩니다.
만약 아이템이 column 갯수를 넘어가게 되면 위와 같이 다음 row 로 아이템을 넘기게 됩니다.
grid-template-columns 에는 %, rem, em 같은 모든 사이즈 단위를 사용할 수 있습니다. 뿐만 아니라 grid 내부에서만 사용할 수 있는 단위 fr이 있는데, fr에 대해서 간단히 알아보고 넘어 가도록 하겠습니다.
fr unit
fr은 fraction의 줄임말로 화면을 효과적으로 나눌 때 쓰는 단위입니다. grid-template-columns: 1fr 2fr 1fr; 을 적용해 보도록 하겠습니다.
어떤가요? 느낌이 오시나요? 얼추보면 column 사이즈의 비중이 1:2:1이 된 것을 알 수 있습니다.
그렇습니다. fr은 grid 내에서 해당 비중만큼 사이즈를 나누어 구성합니다. 정확한 숫자를 넣어야 했던 %보다 훨씬 쉽게 사용할 수 있습니다. 예를 들어 화면을 3등분할 때, width: 33.333333% 이런식으로 입력하기 보단 grid-template-columns: 1fr 1fr 1fr; 처럼 쉽게 수치를 입력할 수 있습니다.
grid-template-rows
column을 설정할 때에는 grid-template-rows 속성을 사용합니다.
.container {
display: grid;
grid-template-columns: 100px 200px 300px;
grid-template-rows: 100px 200px;
}A, B, C가 포함된 첫번째 컬럼은 100px, D, E, F가 포함된 두번째 열은 200px로 영역을 차지한 것을 볼 수 있습니다. column과 마찬가지로 rem, em, %, fr 등의 다양한 단위를 사용할 수 있습니다.
grid 안에 아이템 배치하기
grid는 flex와 달리 아이템을 자기가 원하는 위치에 배치할 수 있습니다.
<style>
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px 100px;
}
</style>
<div class="container">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
<div class="box e">E</div>
<div class="box f">F</div>
<div class="box g">G</div>
<div class="box h">H</div>
<div class="box i">I</div>
</div>그림과 같이 3개의 비율로 열을 나누고, 100px짜리 3개의 로우을 만들었습니다. 우선 A 박스로 1열 전체를 채우고, 나머지 아이템들을 두 번째 컬럼부터 배치되도록 해보겠습니다.
.a {
grid-column: 1 / 4;
}A 박스가 지니고 있는 클래스 a에 grid-column: 1 / 4; 를 주었더니 하나의 로우를 차지한 것을 알 수 있습니다. 이 코드의 의미는 첫번쨰 컬럼에서 4번째 컬럼까지 차지하라 것입니다. 그런데 컬럼 번호는 어떻게 나눌까요?
로우와 컬럼의 번호는 맨 안쪽부터 1번으로 하여 하나씩 커집니다. 그래서 아까 grid-column: 1 / 4; 에 의해 A 박스가 1번에서 4번까지 전체 열을 차지하게 됩니다.
.b {
grid-column: 1 / 3;
grid-row: 2 / 4;
}B는 grid-column과 grid-row를 같이 부여하였는데, 위와 같이 column과 row를 조합하면 grid layout 내에 원하는 위치 어디든 배치를 할 수 있게 됩니다.
실전 예제) 웹페이지 layout 구성하기
이번에는 grid를 활용하여 위 그림과 같은 대표적인 웹페이지 레이아웃을 만들어 보도록 하겠습니다. 실제 코드를 작성하기 전에 먼저 해야할 것은 column과 row를 나누는 작업입니다.
저는 위 그림과 같이 2개의 column과 3개의 row로 화면을 쪼개보도록 하겠습니다.
.container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 100px 500px 100px;
}column은 1: 2 비율로 화면을 나눴고, row의 경우 100px과 500px, 100px로 나눴습니다. 그랬더니 아직 배치를 안 했기 때문에 위와 같이 화면이 나오는 것을 알 수 있습니다. 이제 각 영역별로 제 위치를 찾아 주도록 하겠습니다.
.header {
grid-column: 1 / -1;
grid-row: 1;
}
.side-bar {
grid-column: 1;
grid-row: 2;
}
.main {
grid-column: 2;
grid-row: 2;
}
.footer {
grid-column: 1 / -1;
grid-row: 3;
}이제 우리가 의도했던 대로 화면이 배치 되는 것을 볼 수 있습니다.
그런데 우리가 쓰지 않은 문법이 하나 있습니다. header와 footer의 경우 grid-column: 1 / -1; 의 표현을 사용했는데 이 것은 처음부터 끝까지 컬럼을 차지하겠다는 의미입니다. 여기서 -1은 마지막 컬럼을 뜻하며, 만약에 -2라고 하면 마지막에서 두번째 컬럼을 뜻합니다.
그런데 숫자를 컬럼과 로우의 숫자를 일일이 모든 내부 아이템마다 넣어주자니 조금 코드가 번잡한 느낌이 있습니다. 이번에는 grid-area를 통해서 조금 더 직관적인 코드로 바꿔보도록 하겠습니다.
grid-template-areas
grid는 각 영역에 이름을 부여할 수 있습니다. 그리고 부여된 이름을 각 아이템에서 배치에 사용할 수 있습니다.
.container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 100px 500px 100px;
grid-template-areas:
"header header"
"side-bar main"
"footer footer";
}위 코드를 보면 grid-template-columns, grid-template-rows로 인해 3X2의 레이아웃이 생겼습니다. 그리고 grid-template-areas에서 3X2 레이아웃에 맞추어 각 영역을 구분해 주었습니다. 이름 명명에는 규칙이 없고, 여기서 정의된 이름은 나중에 grid 내부 아이템에서 위치를 정할 때 사용됩니다. 이제 grid-area 속성을 통해 각 아이템의 위치를 정해보도록 하겠습니다.
.header {
grid-area: header;
}
.side-bar {
grid-area: side-bar;
}
.main {
grid-area: main;
}
.footer {
grid-area: footer;
}grid-area: header 처럼 grid-templates-areas 에서 정의한 이름들을 사용할 수 있습니다. 이제 브라우저를 실행해보도록 하겠습니다.
grid-column 과 grid-row 가 빠졌음에도 정상적으로 우리가 의도한 대로 화면에 배치되는 것을 알 수 있습니다.
한 가지 더) 반응형 layout 만들기
모바일 기기에서 웹페이지를 보면 화면 폭이 좁기 때문에 Side-Bar를 두지 않고, 아래처럼 위로 Header 바로 밑에 위치 시키는 경우가 많습니다.
위와 같이 하려면 어떻게 해야 할까요? media-query와 grid-template-column 과 grid-template-areas 을 활용하면 어렵지 않게 구현할 수 있습니다.
혹 media-query를 잘 모르신다면 이(링크)에서 간략하게 개념을 보고 오시는 것을 추천드립니다.
@media (max-width: 600px) {
.container {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"side-bar"
"main"
"footer";
}}화면의 폭이 600이하 일 때는 grid-template-columns: 1fr; 으로 column을 하나로 변경했습니다. 그리고 grid-template-areas 에서 위에서부터 각 아이템이 하나의 영역을 차지하도록 변경했습니다.
실행 해보면 작은 화면에서 그리고 큰 화면에서 정상적으로 잘 작동하는 것을 알 수 있습니다.
Wrap Up
이로써 간단히 grid에 대해서 알아 보았습니다. 이외에도 grid에는 유용하면서 편리한 기능들이 무궁무진합니다. 추가적으로 더 궁금하시다면 이 글(링크)에서 공부해보시는 것을 추천드립니다.
위 예제에서 사용했던 모든 코드는 아래 github에 올라가 있습니다.
Reference
https://medium.com/free-code-camp/learn-css-grid-in-5-minutes-f582e87b1228
https://medium.com/better-programming/grid-vs-flexbox-which-one-should-you-be-using-471cb955d3b5
