프론트엔드 기본개념 복습/CSS

[CSS] Grid

콘요맘떼 2022. 2. 26. 17:54

CSS Grid

  Grid는 현 시점에서 가장 궁극적인 형태의 레이아웃을 제공해준다. 이미 Flex만으로도 레이아웃을 잘 짤 수 있는데 Grid를 공부해야 하는 이유는 무엇일까? Flex는 1차원의 개념에서 그치지만 Grid는 2차원의 레이아웃을 표현할 수 있다. Grid를 활용하게 되면 여러 라인의 아이템을 표현할 때 불필요한 row 혹은 column 컨테이너를 만들어주지 않아도 된다. 물론 Grid가 Flex보다 무조건 좋은 것이라고 볼 수는 없다. Grid는 전체적인 레이아웃을 잡아주거나 2차원의 레이아웃을 표현할 때 강점을 지닌다. 하지만 1차원의 레이아웃을 표현할 때는 단순한 Flex를 활용하는 것이 훨씬 효과적이다. 따라서 상황에 따라 Flex와 Grid 중 필요한 것을 적절히 활용할 수 있는 것이 중요하다.

 

 

Grid 구성 요소

  Flex와 마찬가지로 Grid 역시 container와 item의 조합으로 표현되며 각각에 적용할 수 있는 스타일 statement가 다르다. (솔직히 말해서 Flex와 마찬가지로 Grid 역시 container의 스타일링으로 대부분의 레이아웃이 처리된다. item의 스타일을 터치하는 일은 생각보다 별로 없다.)

 

Grid Container 스타일

1. display : grid;

  Grid 컨테이너를 만들어주기 위해서는 우선적으로 container의 display를 grid로 설정해줘야 한다. 만약 container를 inline-block으로 처리하고 싶다면 inline-grid를 대신 적용해주면 된다.

 

2. grid-template-columns / grid-template-rows - 행과 열 레이아웃 조정

  Grid의 행과 열의 레이아웃을 짤 수 있게 해주는 구문으로 grid css의 가장 중요한 개념 중 하나이다. 가장 기본적인 형태로 grid-template-column(rows)를 활용하는 것은 전혀 어렵지 않다. 아래와 같이 각각의 열 혹은 행의 크기를 지정하면 행-열의 개수와 각각의 크기를 정해줄 수 있다.

 

위의 grid 스타일링이 적용된 실제 화면

  실제로 grid-template-columns(rows) 스타일링을 활용할 때는 다양한 단위 혹은 함수를 사용한다. 꼭 숙지하도록 하자.

(1) fr (fraction)

  가변 크기 단위이다. fr은 남은 영역에서 얼만큼을 차지할 지를 지정해줄 수 있다. (만약 react-native를 사용해본 사람이라면 flex 속성을 지정해준다고 생각하면 이해가 바로 될 것이다.) fr은 고정 단위와 함께 사용될 수도 있다.

  첫 번째 예시이다. 위와 같이 1fr을 세 개 지정해주면 3개의 열이 형성되고 각각의 열이 부모 container의 width를 공평하게 나눠 가진다.

 

  두 번째 예시이다. 첫 번째 열은 지정한 대로 100px을 가지며 두 번째와 세 번째 column이 나머지 영역을 나눠 가진다. 그 중에서 1fr을 지정한 두 번째 열은 남은 영역의 3분의 1을, 2fr을 지정한 마지막 열은 남은 영역의 3분의 2를 차지한다.

 

 

너무 작아서 잘 보이지 않지만 오른쪽 끝에 조그맣게 노랑색과 보라색이 있다.

  마지막 예시이다. (개인적으로 궁금했어서 직접 작성해본 건데 혹시나 또 궁금한 사람이 있을까봐 첨부한다.) 만약 고정 단위들과 함께 사용한다면 auto는 1fr처럼 작동한다. 그러나 fr과 함께 사용한다면 item 자체의 size가 적용되므로 주의해야 한다.

 

(2) min-content, max-content

  그리드 아이템이 포함하는 내용의 최소 크기 혹은 최대 크기를 의미한다. 이후에 소개할 minmax( ) 함수와 기가막힌 궁합을 보여준다.

 

(3) repeat( )

  위의 예시에서는 기껏해야 3개의 행/열밖에 존재하지 않았다. 그런데 만약 열의 개수가 100개라면? 당연히 1fr을 백 번 입력할 걱정은 안 해도 된다. repeat( ) 함수는 반복되는 값을 자동으로 처리하게 해준다. 첫 번째 인자에는 반복 횟수, 두 번째 인자에는 반복될 값이 들어간다. 정말 단순하게 보면 repeat( )는 그냥 우리가 임의로 여러번 타이핑해주는 것처럼 두 번째 인자를 복사해준다고 생각하면 된다. 그렇기 때문에 repeat( )문과 다른 크기 단위를 함께 사용할 수도 있으며 반복될 값에 여러 단위를 적어줄 수도 있다.

 

repeat(3, 1fr) → 1fr 1fr 1fr
100px repeat(2, 1fr) → 100px 1fr 1fr
repeat(2, 100px 1fr 2fr) → 100px 1fr 2fr 100px 1fr 2fr

 

(4) minmax( )

  값의 범위를 지정해줄 수 있다. 첫 번째 인자에는 최소값이, 두 번째 인자에는 최대값이 들어간다. 아래 예시의 경우 각각의 열은 무슨 일이 있어도 400px 이상의 너비를 가진다. minmax( ) 함수는 보통 repeat( ) 함수 내에서 두 번째 인자로 많이 활용된다. minmax( )의 최소값 인자에 앞서 언급한 min-content 혹은 max-content를 지정하는 경우가 종종 존재한다. 특히 min-content의 경우 container에서 item의 사이즈를 알 필요 없이 최소값을 지정해주고 item의 사이즈는 해당 item에서 알아서 처리하면 되므로 보다 효율적인 구조의 코드를 구현할 수 있다.

 

(5) auto-fill, auto-fit

  auto-fill과 auto-fit은 repeat( ) 함수에서 반복 횟수를 담당한다. 둘을 활용하게 되면 반복 횟수를 직접 지정하지 않고 가능한 최대한 많은 아이템을 채워줄 수 있다. auto-fill과 auto-fit의 차이는 아이템들이 한 줄을 다 채우지 못할 때 발생한다. auto-fill의 경우에는 아이템이 꽉 찼을 때와 같이 비율을 유지하며 auto-fit은 아이템을 최대한 늘려서 남은 공간을 꽉 채운다. 아래 예시를 보면 이해가 바로 될 것이다.

auto-fill을 적용하였을 때 (최소값인 50px 유지)
auto-fit을 적용하였을 때 (각각의 아이템들이 stretch됨)

 

  물론 아이템들이 최소한 한 줄을 꽉 채운다면 auto-fit도 똑같이 동작한다.

 

 

3. row-gap, column-gap, gap : 아이템 간 간격 지정

  개인적으로 grid에서 가장 유용하다고 생각되는 기능 중 하나이다. 아이템 간에 일정한 간격을 지정해줄 수 있다. 특히 아이템 간 분리선을 그려주고 싶을 때 grid-container에 원하는 분리선의 색상에 해당하는 background-color을 지정해주고 item들에 다시 background-color을 지정하는 방식을 즐겨 사용한다. (react-native에서는 grid 스타일링이 안 되기 때문에 간격을 지정해주려면 React.cloneElement를 활용해서 index 검사 후 margin을 지정해주는데 grid가 몇 만배는 낫다.)

 

 

4. grid-auto-columns, grid-auto-rows : grid-template-*의 손길을 닿지 못한 애들 처리하기

  grid-auto-columns(rows)는 앞서 언급한 grid-template-columns(rows)가 처리하지 못한 아이템들에 대해서 일괄적인 스타일링을 지정할 수 있도록 한다. grid-template-columns(rows)면 충분한 것 같았는데 처리하지 못했다니 이게 무슨 말일까? 다음 예시를 보면 바로 이해가 될 수 있다.

  사실 여태까지 보여준 코드에서는 item에 직접 100px의 height를 지정해줬다. 이번 예시에서는 해당 스타일링을 제외하고 container에서 100px을 지정해주기로 했다. 그런데 그냥 100px을 지정해줬더니 두 번째 행부터는 100px이 아니라 auto가 지정되어 버렸다. 100px을 다음 행에도 지정해주기 위해 repeat( )를 써보려고 했다. 하지만 생각해보니 몇 개의 행이 사용될 지 우리는 알 수가 없다.

  이러한 이유로 활용하는 것이 grid-auto-columns(rows)이다. grid-auto-columns(rows)를 활용할 때는 지정할 값만 적어주면 된다. 위의 예시에서 grid-auto-rows를 적용시켜 보겠다.

첫 번째 행 이후에도 똑같이 100px이 적용된다 (야호)

  그런데 코드를 보니까 100px을 두 개의 스타일 구문으로 적어주는 게 거슬린다. 그냥 한 번에 모든 행은 100px로 고정하자!라고 정하면 편하지 않나? grid-auto-* 속성이 가장 빛을 말하는 것은 바로 이 순간이다. 위 코드에서 grid-template-rows를 삭제해도 결과는 동일하다. 왜냐하면 모든 행들이 grid-template-rows의 영향을 받지 않은 auto row들이 되고 grid-auto-rows 아래로 들어가기 때문이다. 이처럼 grid-auto-* 속성은 전체 아이템에 대해 동일한 사이즈를 지정해줄 때 단독으로 많이 사용된다.

 

 

Grid 아이템 영역 지정해주기

  여태까지 우리는 Grid 컨테이너의 행과 열을 조정하여 여러 가지 셀을 만들었다. 자 이제 만들어놓은 셀들에 아이템을 어떻게 넣어줄 지 우리 입맛대로 고를 수 있다. 

  이제부터 몇 가지 방법들을 활용하여 아래와 같은 레이아웃을 만들어볼 것이다. 아래 html에서 오직 grid만을 활용할 것이다. (container는 그냥 grid에 대한 이해의 편의를 위해 삽입하였다.)

 

1. grid-column(row)-start(end)

  Grid 아이템에 적용하는 속성이다. 아이템이 시작하는 곳과 끝나는 것의 라인 번호를 지정해주는 방식이다. 라인 번호는 1부터 시작한다. 바로 위에 있는 이미지에 라인 번호를 표기하면 다음과 같다.

  예를 들어서 main은 다음과 같이 지정해주면 된다. (main을 제외한 전체 코드는 해당 깃허브 링크 확인)

 

  grid-column 혹은 grid-row를 활용하면 시작 라인번호와 끝 라인번호를 한 번에 지정해줄 수 있다. "시작라인번호 / 끝라인번호"와 같은 양식을 따르면 된다. 예를 들어서 위에서 제시한 main의 스타일링은 4줄의 스타일링 코드를 2줄로 줄일 수 있다. (깃허브 링크)

  코드는 더욱 간단해질 수 있다. 보통 우리는 '아이템이 몇 번 칸부터 몇 번까지 차지하게 해야지'라고 생각하기 보다는 몇 번부터 '몇 칸을' 차지하게 해야지라고 생각하는 경우가 많다. 아주 고맙게도 span을 사용하면 끝 라인번호 대신 몇 칸의 셀을 차지할지를 지정해줄 수 있다. 포멧은 "grid-column(row) : 시작라인번호 / span 차지할칸수"이다. (깃허브 링크)

 

2. grid-template-areas

  grid-template-areas는 직접 영역에 이름을 붙여주는 방법이다. 개인적으로 grid-column(row)보다 직관적인 방법이라고 생각되지만 일정 규모 이상에서는 부적합하다고 생각되는 방법이다. 컨테이너 속성인 grid-template-areas는 각 셀의 자리에 그에 위치할 아이템의 이름을 적어주면 된다. 비워둘 칸은 .을 적어두면 되며 아이템 이름은 해당 아이템의 grid-area 속성으로 지정해줄 수 있다. (주의) 이름은 따옴표 안에 넣어주면 안 되며 각각의 row가 하나의 "" 안에 들어간다. 사실 직접 보는 것이 가장 이해가 빠를 것이다. 아래 예시에서는 칸 비워두기(.)의 예시를 보여주기 위해 nav가 차지하는 셀을 하나 제외했다.

 

'프론트엔드 기본개념 복습 > CSS' 카테고리의 다른 글

[CSS] translate vs positioning  (0) 2022.04.09
[CSS] currentColor  (0) 2022.04.09
2021-10-02 반응형 웹  (0) 2021.10.03
2021-09-22 Scss, styled-components  (0) 2021.09.23
2021-09-17 CSS Inline과 Block 비교  (0) 2021.09.17