웹이 나오기 시작한 초창기에는 종종 table(표)을 사용해 레이아웃을 구성하였다. 그러나 시멘틱한 마크업의 중요성이 대두되며 점차 이 방식은 지양하게 되었는데, 애초에 table이 표 형식의 데이터를 관리하고 제어하기 위해 만들어졌기 때문이다. 또한 table로 구성된 레이아웃은 반응형 디자인을 고려하기에는 적합하지 않았다.
이후 table의 대안으로 꽤 오랜 기간 사용해왔던 것이 float이다. 그러나 역시 float도 본래의 용도는 이미지와 텍스트의 레이아웃이기 때문에 우리가 원하는 복잡한 어플리케이션 레이아웃을 구현하기에는 적합하지 않았고, 여전히 반응형 디자인에서 제어가 어렵다는 단점이 있었다.
결국 CSS Working Group은 table과 float의 단점을 커버하면서, ‘레이아웃'의 용도에 적합한 Grid Layout Model을 만들게 되었다. 앞서 살펴보았던 Flex를 통해 손쉬운 반응형 레이아웃을 구현할 수 있었다.
Flex는 부모 요소 안에서 한 방향으로만 아이템들을 배치할 수 있지만, Grid는 행과 열, 두 가지 방향으로 배치가 가능하기 때문에 어렵고 복잡한 레이아웃 작성에 매우 적합하다.
1. Grid
1.1 grid로 할 수 있는 것들
Grid는 1차원, 2차원 레이아웃을 구상할 수 있다. 아래와 같이 헤더-사이드바-컨테이너-푸터로 이루어진 기본적인 웹 페이지의 전체적인 레이아웃을 짜는 것이 가능하다.
Grid 안의 아이템들도 또다시 grid 레이아웃으로 만드는게 가능하다. 아주 작은 텍스트 단위의 요소도 grid를 사용하여 아이템을 배치할 수 있다.
Grid 레이아웃으로 쉽게 만들 수 있는 홈페이지의 예이다. 헤더-사이드바-컨테이너로 구성되어 있고, 컨테이너 안의 아이템들도 grid를 사용한 것을 확인할 수 있다.
1.2. 그리드 용어정리
그리드 컨테이너 (Grid Container)
grid를 적용하는 전체 영역을 의미. 열(Columns)과 행(Rows)을 가지며, 그리드 아이템(Items)을 배치
그리드 아이템 (GridItem)
grid 컨테이너의 자식 요소들,이 아이템들이 grid 규칙에 의해 배치
그리드 라인(Grid Line)
grid를 그리는 행(Row)/열(Column)을 그리는 선
각 선은 라인 넘버를 가지며 그리드 아이템을 배치하는 기준이 된다.
그리드 트랙 (Grid Track)
grid 라인 사이의 행(Row) 또는 열(Column) 공간
그리드 셀 (grid Cell)
grid의 한 칸을 가리키는 말 (유닛으로 부르기도 한다)
4개의 그리드 라인이 모여 그려지는 한 칸의 공간
그리드 번호(Grid Number)
grid 라인의 각 번호
그리드 영역(Grid Area)
4개의 그리드 라인으로 둘러싸인 공간으로 그리드 셀이 묶인 영역
식별자를 통해 요소를 배치
그리드 갭(Grid Gap)
그리드 거터(Grid Gutters)
행(Row) 또는 열(Column) 사이의 간격
1.3. 개발자 도구로 그리드 체크하는법
Chrome에서 개발자 도구를 이용하면 HTML 요소에 grid 속성이 적용된 요소는 옆에 버튼이 생기게 되는데 이 버튼을 누르고 닫음으로써 grid 요소의 배치, 속성, 크기를 파악할 수 있다.
맥은 <command + option + i>, 윈도우는 <ctrl + shift +i> 또는 F12를 이용하여 개발자 도구로 진입할 수 있다.
또한, Styles 탭에서 display : grid; 속성 옆의 버튼을 이용해서 요소에 grid의 다양한 속성을 바로 적용하여 어떻게 변하는지 바로 확인할 수 있다.
Styles 탭 옆의 Layout 탭에 들어가게 되면 그리드가 적용된 요소를 더욱 상세하게 볼 수 있다.
Show track sizes : 그리드 셀(Grid Cell)의 크기를 표시한다.
Show area names : grid-template-areas속성이 적용되어 있다면, 그 영역의 이름을 표시한다.
Extend grid lines : 그리드 라인(Grid Line)을 확장한다.
1.4. grid 사용법
Grid는 Flex와 마찬가지로 HTML 구조에 컨테이너와 아이템, 이렇게 두 가지 요소가 필요하다. 컨테이너는 부모 요소로, Grid 레이아웃의 영향을 받는 전체적인 공간이다. 반면 아이템은 자식 요소로, 컨테이너 내부에서 설정된 속성에 따라 배치된다. 이를 Grid에서는 각각 그리드 컨테이너(Grid Container)와 그리드 아이템(Grid Item)이라 한다.
grid를 사용하기 위해선 flex 처럼 CSS에서 display 속성을 부여하는 과정이 필요하다. 컨테이너display:grid;를 적용하면 이후 Grid가 제공하는 속성을 다양하게 사용할 수 있다.
선언 시 즉각적으로 아이템들이 가로로 배치되는 flex와 달리, grid는 display:grid;선언을 해도 변화를 확인하기 어렵다. 왜냐하면 grid 레이아웃이 되었지만, 아직 컨테이너가 하나의 열(row)밖에 없어 아이템들이 기본정렬을 유지하고 있기 때문이다. 컨테이너에 grid-template-columns, grid-template-rows 속성을 추가하여 행과 열을 추가함으로써 그리드 형태를 명확히 확인할 수 있다.
.container{
display:grid;
}
2. Grid row , Grid column
2.1. grid-template-rows, grid-template-columns
Grid는 행과 열로 이루어져 있다. 행은 row, ‘가로'이고 열은 column, '세로'이다. grid row와 column을 사용하기 위해서는 template 속성을 사용해 행과 열의 크기를 지정해 주어야 한다. 여기서 주의할 점은 행과 열의 개수가 아닌 크기를 지정하는 것이다.
grid-template-columns : column(열)의 넓이(크기) 지정하기
grid-template-rows : row(행)의 높이 지정하기
다음은 4개의 아이템의 column과 row에 각각 350px, 200px을 준 예제이다.
fr 은 fraction의 줄임말로, fraction을 직역하면 ‘분수’라는 뜻을 가지고 있다. grid 에서는 그리드 컨테이너에서 사용할 수 있는 공간의 일부를 나타내는 단위를 의미하는데, fr 단위를 사용하면 그리드 내부의 레이아웃 분할을 자동으로 계산해서 적용할 수 있다. 그리드 레이아웃에서 그리드 아이템의 크기를 지정할 때 px 을 이용하면 항상 크기가 고정되기 때문에 반응형 웹 디자인에는 적합하지 않다. 그래서 상대적인 크기를 지정할 수 있도록 fr 단위를 사용하면, 더 편리하게 반응형 디자인을 적용할 수 있다. 예를 들어 grid-template-columns: 1fr 1fr 1fr; 이라는 코드를 적는다면, 컨테이너 안 그리드 아이템의 크기는 1 : 1 : 1 의 비율로 각각 적용된다.
grid-item이 사용자가 명시적으로 지정해준 grid-template-columns 또는 grid-template-rows 에서 벗어난 위치에 존재하게 될 때, 트랙의 크기를 암시적으로 지정하는 속성이다. 쉽게 말하자면, grid 행(rows)/열(columns) 트랙 크기를 자동으로 설정한다.
grid-auto-rows
grid item이 grid-template-rows로 지정한 명시적 행 외부에 존재하는 경우 암시적 행의 크기가 적용된다. 앞으로 추가될 수 있는 모든 행의 높이를 정해주고 싶다면 grid-auto-rows를 적용해주면 된다.
grid-auto-columns
grid item이 grid-template-columns로 지정한 명시적 열 외부에 존재하는 경우 암시적 열의 크기가 적용된다. 암시적 크기가 적용된 행과 열은 오직 양수만 사용할 수 있다 (음수는 사용이 불가하다)
기본적으로 grid에서 각 행의 높이는 지정해주지 않는 이상 콘텐츠의 크기를 가지기 때문에 각각 다르다.
각 행의 높이를 같게 만들기 위해서 grid-template-row 속성을 이용해 여러 가지 여러 가지 방식으로 높이 값을 지정해줄 수 있지만, 이 높이 값은 ‘앞으로 추가될 아이템'에는 적용되지 않는다. grid-template-rows는 현재 정의되고 있는 행의 높이만을 설정할 뿐이기 때문이다. 아이템이 더 추가된다면 행의 높이가 달라지고, 그럼 grid-template-rows를 다시 한번 수정해야 한다는 번거로움이 있다.
Gap은 그리드 컨테이너와 아이템 요소들의 간격을 설정하는 속성이다. gap 속성값에는 우리가 사용하는 각종 단위가 들어갈 수 있다. 길이를 나타내는 단위인 em, rem, px, vmin , vmax나 퍼센티지(%)를 사용 가능하며, calc() 함수를 이용하여 계산된 값도 사용할 수 있다. 하지만 fr 단위는 사용이 불가하다는 점에 주의해야 한다.
fr 단위가 gap의 속성값이 될 수 없는 이유는, fr은 사용 가능한 공간을 분배하는 단위이기 때문이다. 아래 예시처럼 grid-template-columns: 1fr 1fr 1fr; 라는 속성을 컨테이너에 적용하면, 컨테이너의 사용 가능한 넓이를 고려하여 1 : 1 : 1의 비율로 분배하는 것이 fr의 역할이다. 하지만, grid item 요소들 사이에는사용 가능한 공간이 존재하지 않고, 서로 붙어있는 상태이다. 따라서아이템 간의 간격을 벌리는 속성인 gap에 fr 단위가 적용되지 않는 것이다.
아래 예제는 gap:2fr을 그리드 컨테이너에 부여하였지만 적용되지 않는 모습이며, 개발자 도구에서도 마찬가지로 fr이 잘못된 속성값이라 표시되는 것을 확인할 수 있다.
3.2. margin과 gap의 차이점
margin의 경우 인접한 요소의 존재와 상관없이 스타일이 적용되 불필요한 공간을 만든다.
grid-gap에 부여하는 첫 번째 값은 row-gap, 두 번째 값은 column-gap이다. 각자 다른 크기와 단위를 섞어서 사용할 수 있다. 만약, row와 column에 같은 크기의 gap을 주고 싶다면 grid-gap 단일 값을 사용하는 동시에 적용하는 것이 더 효율적이다.
지금까지 배운 grid-column-start , grid-column-end , grid-row-start , grid-row-end 속성을 사용하여 grid 셀의 영역을 지정할 수 있다. 하지만 이렇게 column과 row에 start와 end를 각 각 지정해주기에는 코드가 너무 길어지게 된다. start와 end를 한번에 지정 하려면 start와 end의 축약 속성인 grid-column , grid-row를 사용할 수 있다.
4.4. grid-column & grid-row
위에서 배운 grid-column-start와 grid-column-end 는 grid-column으로, grid-row-start와 grid-row-end는 grid-row로 축약하여 start와 end를 한 번에 지정하여 사용할 수 있다.
현재 레이아웃은 임의의 3x3 공간을 가지고 있다고 생각하자. 이에 따라 컨테이너의 자식요소들의 너비를 설정해 준다. grid-template-columns 의 비율은 1:1:1, grid-template-rows 의 비율은 1:3:1로 설정하여 2번째 컬럼이자 컨텐츠 요소들의 비율을 키워보도록 작성한다.