CSS 그리드(Grid) - 2. 그리드 기초와 속성

1. 그리드 기초

그리드는 그리드를 선언하는 요소와 하위의 자식 요소들로 구성됩니다.

그리드를 구성하는 자식요소들을 "아이템" 이라고 하며, 자식 요소들의 태그 종류에 관계 없이, 그리드 바로 하위의 자식요소들만 아이템이 됩니다.

그리드 선언은 CSS 속성으로

display: grid;

로 시작합니다.

그리드 속성 선언 만으로는 자식 아이템들에 아무런 영향을 미치지 않습니다. 추가 그리드 속성이 정의되지 않으면 "display: grid;" 는 "display: block;" 과 같습니다.

그리드는 모눈 종이처럼 행과 열로 구성됩니다.

따라서 행과 열을 속성으로 정의해야 비로소 그리드 레이아웃의 기능을 하게 됩니다.

동적으로 아이템을 추가하는 경우가 아니면 아이템 갯수가 이미 정해져 있으므로, 행과 열의 갯수와 너비/높이를 정해주는 것만으로 레이아웃의 기본적인 모양이 완성됩니다.

아이템의 갯수가 정해져 있으므로 열 갯수만 정해면 행 수는 자동으로 정해집니다.

다음과 같이 6개의 아이템으로 구성된 HTML 요소를 한 행에 3개의 아이템이 있는 그리드로 만들어보겠습니다.

그리드 요소 속성에 "grid-template-columns" 속성을 추가합니다.

grid-template-columns: 25% 25% 50%;

아이템들은 다음과 같이 그리드 너비 400px를 25% : 25% : 50% 의 비율로 자리를 차지하게 됩니다.

다음과 같은 HTML 그리드에

<div class="grid">
    <div class="item">아이템1</div>
    <div class="item">아이템2</div>
    <div class="item">아이템3</div>
    <div class="item">아이템4</div>
    <div class="item">아이템5</div>
    <div class="item">아이템6</div>
</div>

CSS 그리드를 선언하면

.grid{
    width: 400px;
    display: grid;
    grid-template-columns: 25% 25% 50%;
}
.grid .item{
    min-height: 100px;
}

다음과 같이 간단한 그리드가 생성됩니다.

그리드는 열 갯수가 정해지면 자동으로 열 갯수에 맞춰 아이템들이 채워지기 때문에 모든 행의 아이템 너비는 자동으로 정해집니다.

2. 그리드 고정 너비와 자동 너비 설정

레이아웃을 만들다보면 그리드 전체 너비가 변해도 특정 아이템의 너비는 변하지 않고 고정 크기를 가지도록 해야할 경우가 있습니다.

아이템 너비를 고정하는 것은 픽셀, 또는 em으로 크기를 지정하면 고정할 수 있습니다.

그리고, 이런 경우 고정된 아이템을 제외한 다른 아이템의 너비가 전체 그리드 영역 너비 변화에 맞춰 늘어나거나 줄어들어야 합니다.

그리드에서는 이런 가변 아이템을 위해 "auto" 속성을 지원합니다.

앞서의 그리드 예에서 첫 번째와 세 번째 열 아이템 너비를 "120px" 로 고정하고, 두 번째 아이템 너비를 "auto" 로 지정하면 전체 그리드 너비에서 "240px" 를 뺀 나머지 너비가 두 번째 아이템 너비로 자동으로 할당됩니다.

.grid{
    width: 400px;
    display: grid;
    grid-template-columns: 120px auto 120px;
}

만약 "auto" 설정한 열이 2개 이상이면 고정된 너비를 가진 아이템(들)의 너비를 뺀 나머지 너비 값이 "auto"로 설정한 아이템 갯수만큼 같은 너비로 배분됩니다.

.grid{
    width: 550px;
    display: grid;
    grid-template-columns: auto auto 100px;
}

3. 그리드 행 높이 설정

열 너비를 설정하는 속성(grid-template-columns)과 대칭인 속성으로 행 높이를 정하는 "grid-template-rows" 속성이 있습니다.

속성 값으로 행 사이의 여백을 공백으로 띄워서 나열해 행 높이(들)를 정의합니다.

그리드 행과 열 너비와 높이에가 다음과 같이 정해지면

.grid{
    width: 550px;
    display: grid;
    grid-template-columns: auto 150px; /* 첫 번째 열 너비는 550px - 150px = 400px 로 설정 */
    grid-template-rows: 60px 200px 30px;
}

다음과 같이 그리드가 만들어집니다.

그리드 높이 값이 정의된 경우 열 아이템 너비에 "auto" 속성을 사용한 것처럼 행 아이템 너비에도 "auto" 너비 값을 사용할 수 있습니다.

.grid{
    width: 550px;
    height: 400px;
    display: grid;
    grid-template-columns: auto 150px; /* 첫 번째 열 너비는 550px - 150px = 400px 로 설정 */
    grid-template-rows: 60px auto 30px; /* 두 번째 행 높이는 400px - 90px = 310px 로 설정 */
}

4. 그리드 여백 설정

그리드는 행과 열 아이템 사이에 적용되는 여백 값을 설정할 수 있는 속성이 기본으로 제공됩니다.

행과 열에 같은 여백 값을 사용할 수도, 행과 열에 각각 다른 여백을 설정할 수도 있습니다.

그리드 여백은 마주보는 아이템 사이에만 여백이 설저되기 때문에 끝나는 행, 또는 열 아이템의 여백을 신경 쓸 필요가 없습니다.

그리드 여백 속성은 다음 3가지 속성으로 설정할 수 있습니다.

속성 설명
grid-gap 행과 열 사이의 여백 설정
패딩이나 마진 속성처럼 속성 값을 1개만 정의하면 행과 열에 같은 여백 값이 적용되며, 2개를 정의하면 행과 열(순서대로) 여백 값이 적용됩니다.
grid-column-gap 열 사이의 여백 설정
grid-row-gap 행 사이의 여백 설정

다음과 같이 행과 열 여백을 각각 지정하면

.grid{
    width: 450px;
    height: 300px;
    display: grid;
    grid-template-columns: auto 150px;
    grid-template-rows: 60px auto 30px;
    gap: 10px 30px; /* 행 사이 여백 10px, 열 사이 여백 30px 적용 */
    margin: 0 auto;
}

다음과 같이 여백이 적용됩니다.

5. "fr"(프렉션) 단위의 이해

"fr" 은 "fraction" 의 약자입니다. 한글로는 "분수", 또는 "나눈 조각" 을 의미합니다. 그리드에서는 행, 또는 열을 나눈 조각을 말하며, 행, 또는 열을 몇 개의 조각으로 나눌 지를 정하는 단위로 사용됩니다.

예를 들어 3열로 된 그리드를 1fr 1fr 2fr 로 3개의 조각으로 나눈다면, 각 열 별로 1조각, 1조각, 2조각을 분배한다는 뜻이고, 전체 그리드 너비에서 1/4(25%), 1/4(25%), 1/2(50%) 을 각각 분배하게 됩니다. 

퍼센트로 나누는 것과 같기 때문에 "fr" 단위 사용에 익숙하지 않으면 퍼센트로 사용해도 됩니다.

실제로 사용할 때는

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

과 같이 컬럼별 너비를 나열해서 비율을 표시합니다. 이 속성 표기는 아이템들을 3열로 배치하고 1 : 1 : 2 의 비율로 전체 그리드 너비를 분배한다는 뜻이 됩니다.

상대 크기로 영역 너비를 설정할 경우, 퍼센트 단위보다는 프렉션 단위를 사용해서 영역 너비를 설정하는 것을 권장합니다.

6. 그리드 영역 매핑하기

행과 열로 나눠서 구획을 정하는 것 까지는 간단하지만, 실제 우리가 웹에서 만드는 레이아웃은 모눈종이처럼 사각형으로 행과 열이 나누어진 레이아웃은 거의 없습니다.

행 전체가 1개의 아이템으로 구성되기도 하고, 행의 1열 셀만 고정 크기이고, 나머지 셀들은 하나로 합쳐져 1개의 셀로 사용되기도 합니다.

그리드 영역 매핑 속성인 "grid-template-areas" 을 사용해 행 안의 셀(들)을 묶어서 영역을 다양하게 구획할 수 있습니다.

웹 페이지를 구성하는 기본 시멘틱 태그로 만든 간단한 웹 페이지 구조를 그리드 영역 매핑을 해서 페이지 레이아웃을 만들어 보겠습니다.

다음과 같은 HTML 레이아웃 페이지를

<div class="grid">
    <header class="item header">헤더</header>
    <h1 class="item title">타이틀</h1>
    <main class="item main">컨텐츠영역</main>
    <aside class="item sidebar">사이드바</aside>
    <footer class="item footer">푸터</footer>
</div>

다음과 같은 웹페이지 레이아웃으로 만들게 됩니다.

그리드로 영역을 구획해서 레이아웃을 만들때는 각 영역들이 구획된 위치를 채워서 자리를 잡게 됩니다.

예를 들어 "사이드바" 영역은 왼쪽의 "타이틀" 영역과 "컨텐츠" 영역을 합친 높이 만큼의 영역을 차지하게 됩니다.

먼저 영역을 구획하기 위해 영역의 이름을 정의해야 합니다.

영역 구획을 총 5개로 할 것이므로 "header", "title", "main", "sidebar", "footer" 5개로 이름을 사용하기로 합니다.

영역 이름은 공백없이 "-", "_" 로 연결해서 긴 이름을 사용할 수도 있습니다.(영역 이름은 한글 이름도 가능합니다.)

다음과 같이 각 HTML 태그에 적용한 클래스에 영역 이름을 "grid-area" 속성으로 지정합니다.

이렇게 클래스와 영역 이름을 연결하면, 클래스를 사용한 태그 영역을 영역 이름으로 제어할 수 있게 됩니다.

.grid .header{grid-area: header;}
.grid .title{grid-area: title; height: 50px; margin: 0;}
.grid .main{grid-area: main; height: 300px;}
.grid .sidebar{grid-area: sidebar;}
.grid .footer{grid-area: footer;}

".title", ".main" 클래스에 높이 값을 지정한 것은 영역 안에 컨텐츠 내용이 들어있다는 것을 가정해서 보기 좋게 하기 위함이며 그리드 영역의 구획에는 영향을 미치지 않습니다.

이제 정의한 그리드 "영역 이름" 들을 사용해 그리드 정의 클래스에 "grid-template-areas" 속성으로 영역의 범위를 설정합니다.

이것을 영역을 매핑(Mapping)한다고 합니다.

.grid{
    width: 600px;
    display: grid;
    grid-template-columns: auto 150px;
    grid-template-areas: "header header" "title sidebar" "main sidebar" "footer footer";
    gap: 10px;
}

"grid-template-columns" 속성으로 2열로 구성된 페이지 레이아웃을 만들기로 했고, 첫 번째 열은 자동으로 너비가 늘어나거나 줄어들면서 채워지도록 "auto" 로 하고, "사이드바"가 위치할 두 번째 열은 "150px" 너비로 고정했습니다.

헤더, 푸터 영역은 셀 1개가 전체 행을 모두 차지하게 됩니다. 

열이 2개로 정의되었으므로 "grid-template-areas" 속성은 (쌍)따옴표로 감싼 2개의 영역 이름을 공백으로 띄워서 1개의 행을 표현하게 됩니다.

한 행의 열 2개를 합치려면 같은 영역 이름을 2개("header header") 표시해서 영역이 행 전체를 차지함을 표시하게 됩니다.

"header header" 는 "header" 이름으로 매핑한 ".header" 클래스를 사용하는 태그가 행 전체를 차지한다는 뜻입니다.

열을 합칠 때는 연달아 위치한 행의 같은 순서 열에 같은 영역 이름을 사용하면 됩니다.

예를 들어 2번째와 3번째 행의 영역을 정의한 "grid-template-areas" 속성 값은 두 번째 오는 값이 모두 "sidebar" 입니다. 이렇게 같은 순서의 열에 영역 이름이 연달아 같으면 두 개의 열을 합쳐서 하나의 열로 표시합니다.

테이블 태그로 테이블을 만들 때 연달아 있는 2개 이상의 열을 합치는 것과 같은 방식입니다.

영역 매핑으로 합쳐진 행(들)이나 열(들)은 웹 브라우저 개발자 도구(F12) 를 사용하면 실제 그리드가 어떻게 구획되어 있는지 확인할 수 있습니다.

영역을 합쳐 구획한 그리드

7. 크롬 개발자 도구에서 그리드 확인하기

크롬 개발자 도구를 사용하면 현재 그리드가 어떻게 나누어져 있는지 쉽게 확인할 수 있습니다.

앞서의 예제들은 그리드 아이템 마다 색상을 다르게 채워서 알아보기 쉽게 만들었지만, 실제로 그리드로 레이아웃을 만들면 그리드 설정이 눈에 잘 들어오지 않습니다.

그럴때는 개발자도구 엘리먼트(Element) 보기 탭에서 그리드 선언 요소를 선택하면 다음과 같이 그리드 분할 아이템들과 여백이 점선으로 구분되어 보입니다.

크롬 개발자도구에서 그리드 구분 영역을 확인하는 화면