도란도란 :: [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에 영향을 받게 됩니다.

 

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

코드를 실행하면 위와 각 자식 요소가 하나의 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 내부의 아이템을 아래와 같이 채우게 됩니다.

 

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

만약 아이템이 column 갯수를 넘어가게 되면 위와 같이 다음 row 로 아이템을 넘기게 됩니다.

grid-template-columns 에는 %, rem, em 같은 모든 사이즈 단위를 사용할 수 있습니다. 뿐만 아니라 grid 내부에서만 사용할 수 있는 단위 fr이 있는데, fr에 대해서 간단히 알아보고 넘어 가도록 하겠습니다.

 

fr unit

fr은 fraction의 줄임말로 화면을 효과적으로 나눌 때 쓰는 단위입니다. grid-template-columns: 1fr 2fr 1fr; 을 적용해 보도록 하겠습니다.

 

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

어떤가요? 느낌이 오시나요? 얼추보면 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; 
}

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

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>

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

그림과 같이 3개의 비율로 열을 나누고, 100px짜리 3개의 로우을 만들었습니다. 우선 A 박스로 1열 전체를 채우고, 나머지 아이템들을 두 번째 컬럼부터 배치되도록 해보겠습니다.

.a {   
    grid-column: 1 / 4; 
}

 

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

A 박스가 지니고 있는 클래스 a grid-column: 1 / 4; 를 주었더니 하나의 로우를 차지한 것을 알 수 있습니다. 이 코드의 의미는 첫번쨰 컬럼에서 4번째 컬럼까지 차지하라 것입니다. 그런데 컬럼 번호는 어떻게 나눌까요?

 

로우와 컬럼의 번호는 맨 안쪽부터 1번으로 하여 하나씩 커집니다. 그래서 아까 grid-column: 1 / 4; 에 의해 A 박스가 1번에서 4번까지 전체 열을 차지하게 됩니다.

.b {     
    grid-column: 1 / 3;     
    grid-row: 2 / 4; 
}
 

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

B는 grid-column grid-row를 같이 부여하였는데, 위와 같이 column row를 조합하면 grid layout 내에 원하는 위치 어디든 배치를 할 수 있게 됩니다.

 

실전 예제) 웹페이지 layout 구성하기

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

이제 우리가 의도했던 대로 화면이 배치 되는 것을 볼 수 있습니다.

그런데 우리가 쓰지 않은 문법이 하나 있습니다. 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 바로 밑에 위치 시키는 경우가 많습니다.

 

See the Pen Untitled by LUPIN-MOM (@lupin-mom) on CodePen.

 

 

 

위와 같이 하려면 어떻게 해야 할까요? 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 에서 위에서부터 각 아이템이 하나의 영역을 차지하도록 변경했습니다.

실행 해보면 작은 화면에서 그리고 큰 화면에서 정상적으로 잘 작동하는 것을 알 수 있습니다.

추가적으로 더 궁금하시다면 이 글(링크)에서 공부해보시는 것을 추천드립니다.

 

반응형