IT/HTML & CSS

이번에야 말로 CSS Grid 배우기

라임웨일 2022. 2. 17. 08:30
반응형

 

CSS 그리드 레이아웃이란?

CSS 그리드 레이아웃(Grid Layout)은 페이지를 여러 주요 영역으로 나누거나, 크기와 위치 및 문서 계층 구조의 관점에서 HTML 기본 요소로 작성된 컨트롤 간의 관계를 정의하는 데 아주 탁월합니다.

테이블과 마찬가지로 그리드 레이아웃은 세로 열과 가로 행을 기준으로 요소를 정렬할 수 있습니다. 하지만, 테이블과 달리 CSS 그리드는 다양한 레이아웃을 훨씬 더 쉽게 구현할 수 있습니다. 예를 들어, 그리드 컨테이너 속 자식 요소를, 마치 CSS로 일일이 위치를 지정해 준 것처럼, 실제로 겹치게 층을 지면서 자리를 잡도록 각 요소의 위치를 지정해 줄 수도 있습니다.

 

Flex와 지금 공부할 Grid의 가장 차이점은

  • Flex는 한 방향 레이아웃 시스템이고 (1차원)
  • Grid는 두 방향(가로-세로) 레이아웃 시스템 (2차원)

이라는 점입니다. 따라서 Flex보다 더 복합적인 레이아웃 표현이 가능하지요.

 

 

호환성

caniuse에 호환성을 보면 IE는 10과 11에서 부분적으로 지원한다고 적혀있고, 그 외 최신 브라우저에서는 동작하는 것을 알 수 있습니다. 사실상 재대로 Grid를 사용하기 위해선 Edge부터 사용 가능하다고 생각하는게 좋을거 같습니다.

용어 정리

예제와 이미지를 통해 Grid에 대해 알아볼게요. Flex와 마찬가지로, 컨테이너와 아이템이 있으면 됩니다. 사실 지금 보면 뭔가 되게 복잡하고 “이게 뭐야..” 하실 수도 있는데, 일단은 어딘가 정리할 필요는 있어서 지금 넣어 보았습니다. 글을 따라서 천천히 읽다 보시면 자연스럽게 이해하고 어느 순간 코드에 Grid를 사용하는 자신을 발견하게 될 것입니다.

 

  • 그리드 컨테이너 (Grid Container)
    display: grid를 적용하는, Grid의 전체 영역입니다. Grid 컨테이너 안의 요소들이 Grid 규칙의 영향을 받아 정렬된다고 생각하면 됩니다. 위 코드 <div class=”container”></div>가 Grid 컨테이너예요.
  • 그리드 아이템 (Grid Item)
    Grid 컨테이너의 자식 요소들입니다. 바로 이 아이템들이 Grid 규칙에 의해 배치되는 거예요. 위 코드에서 <div class=”item”></div>들이 Grid 아이템입니다.
  • 그리드 트랙 (Grid Track)
    Grid의 행(Row) 또는 열(Column)
  • 그리드 셀 (Grid Cell)
    Grid의 한 칸을 가리키는 말이예요. <div> 같은 실제 html 요소는 그리드 아이템이고, 이런 Grid 아이템 하나가 들어가는 “가상의 칸(틀)”이라고 생각하면 됩니다.
  • 그리드 라인(Grid Line)
    Grid 셀을 구분하는 선입니다.
  • 그리드 번호(Grid Number)
    Grid 라인의 각 번호입니다.
  • 그리드 갭(Grid Gap)
    Grid 셀 사이의 간격입니다.
  • 그리드 영역(Grid Area)
    Grid 라인으로 둘러싸인 사각형 영역으로, 그리드 셀의 집합이에요.

Grid의 속성들은 Flex와 마찬가지로,

  • 컨테이너에 적용하는 속성
  • 아이템에 적용하는 속성

이렇게 두 가지로 나뉘어요.

 

부모 요소인 div.container를 Grid Container(그리드 컨테이너)라고 부르고, 자식 요소인 div.item들을 Grid Item(그리드 아이템)이라고 부릅니다.

“컨테이너가 Grid의 영향을 받는 전체 공간이고, 설정된 속성에 따라 각각의 아이템들이 어떤 형태로 배치되는 것”이라고 생각하시면 됩니다. 

<div class="container">
   <div class="item color-1"> item-1 </div>
   <div class="item color-2"> item-2 </div>
   <div class="item color-3"> item-3 </div>
   <div class="item color-4"> item-4 </div>
   <div class="item color-5"> item-5 </div>
 </div>

위의 html 코드가 구체화 된 모습

display: grid;

Grid 컨테이너에 display: grid;를 적용하는 게 시작이에요. 아이템들이 block 요소라면 이 한 줄 만으로는 딱히 변화는 없습니다.

.container {
	display: grid;
	/* display: inline-grid; */
}
/* 그리고 아무 일도 일어나지 않았다 */

inline-grid도 있는데, 이건 block과 inline-block의 관계를 생각하시면 돼요.
아이템의 배치와 관련이 있다기보다는, 컨테이너가 주변 요소들과 어떻게 어우러질지 결정하는 값입니다. inline-grid는 inline-block처럼 동작해요. 이것 역시 Flex랑 비슷하죠?

그리드 형태 정의

  • grid-template-rows : 행(row)의 배치
  • grid-template-columns : 열(column)의 배치
  • -ms-grid-rows
  • -ms-grid-columns

컨테이너에 Grid 트랙의 크기들을 지정해주는 속성입니다. 여러 가지 단위를 사용할 수 있고 섞어서 쓸 수도 있어요. IE 10 ~ 11에서 사용하시려면 IE에서 사용하는 ms 벤더 프리픽스를 같이 사용하여야 합니다.

.container {
	grid-template-columns: 250px 250px 250px 250px 250px;
	/* grid-template-columns: 1fr 1fr 1fr */
	/* grid-template-columns: repeat(3, 1fr) */
	/* grid-template-columns: 200px 1fr */
	/* grid-template-columns: 100px 200px auto */

	grid-template-rows: 150px;
	/* grid-template-rows: 1fr 1fr 1fr */
	/* grid-template-rows: repeat(3, 1fr) */
	/* grid-template-rows: 200px 1fr */
	/* grid-template-rows: 100px 200px auto */
}

grid-template-columns, grid-template-row 코드가 적용된 모습

 

조금 더 자세히 grid-template-columns 코드를 알아볼게요

grid-template-columns: 250px 250px 250px 250px 250px;

 

위 코드는 column을 250px씩 5개 만들겠다는 의미입니다.

grid-template-columns: 1fr 1fr 1fr;

fr은 fraction의 약어인데, 숫자 비율대로 트랙의 크기를 나눕니다. 즉 위의 1fr 1fr 1fr은 균일하게 1:1:1 비율인 3개의 column을 만들겠다는 의미합니다.

서로 다르게 속성을 지정해도 무방합니다.

grid-template-columns: 1fr 3fr 2fr;

 

고정 크기와 가변 크기를 섞어 쓸 수도 있고요.
아래처럼 하면 왼쪽의 첫 번째 column은 100px로 고정되고, 나머지 두 번째 세 번째 column은 2:1의 비율로 유연하게 움직이게 됩니다.

grid-template-columns: 100px 2fr 1fr;

 
 

 

repeat 함수

.container {
	grid-template-columns: repeat(5, 1fr);
	/* grid-template-columns: 1fr 1fr 1fr 1fr 1fr */
}

repeat는 반복되는 값을 자동으로 처리할 수 있는 함수입니다.

repeat(반복횟수, 반복값)을 나타냅니다. 즉, 위 코드의 repeat(5, 1fr) 1fr 1fr 1fr 1fr 1fr과 같아요.
repeat(3, 1fr 4fr 2fr); 이런 식의 패턴도 가능합니다.

 

minmax 함수

최솟값과 최댓값을 지정할 수 있는 함수입니다.
minmax(100px, auto)의 의미는 최소한 100px, 최대는 자동으로(auto) 늘어나게.. 입니다. 즉 아무리 내용의 양이 적더라도 최소한 높이 100px은 확보하고, 내용이 많아 100px이 넘어가면 알아서 늘어나도록 처리해 준 예시입니다.

.container {
	grid-template-columns: repeat(3, 1fr);
	grid-template-rows: repeat(3, minmax(100px, auto));
}
 

auto-fill과 auto-fit

auto-fill과 auto-fit은 column의 개수를 미리 정하지 않고 설정된 너비가 허용하는 한 최대한 셀을 채웁니다.
auto-fill 먼저 살펴볼게요.

.container {
	grid-template-columns: repeat(auto-fill, minmax(20%, auto));
}

auto-fill의 크기를 20%로 설정했으므로, 1개의 row에는 5개의 셀이 들어갑니다.


셀의 개수가 5개보다 모자라면, 아래의 이미지처럼 공간이 남게 되고요.

auto-fill 대신 auto-fit을 사용하면, 남는 공간을 채웁니다.

남는 공간을 비워두는가 또는 채우는가 여부가 auto-fill과 auto-fit의 차이점입니다.

간격 만들기

  • row-gap
  • column-gap
  • gap

그리드 셀 사이의 간격을 설정합니다.

.container {
	row-gap: 10px;
	/* row의 간격을 10px로 */
	column-gap: 20px;
	/* column의 간격을 20px로 */
}
.container {
	gap: 10px 20px;
	/* row-gap: 10px; column-gap: 20px; */
}
.container {
	gap: 20px;
	/* row-gap: 20px; column-gap: 20px; */
}
 
gap : 10px이 적용된 이미지

초기에는 앞에 gird-를 붙여서 grid-gap, grid-row-gap, grid-column-gap이었는데, 브라우저 호환 범위를 넓히기 위해 아래처럼 이전 버전의 이름과 현재 버전의 이름을 둘 다 쓰기도 해요.

.container {
	grid-gap: 20px;
	gap: 20px;
}

IE에서는 gap의 대체 속성이 없기 때문에, IE와 구조를 통일하고 싶으면 아예 처음부터 gap을 사용하지 않고 구조를 설계하는 게 편해요.

그리드 형태를 자동으로 정의

  • grid-auto-columns
  • grid-auto-rows

grid-template-columns(또는 grid-template-rows)의 통제를 벗어난 위치에 있는 트랙의 크기를 지정하는 속성입니다.
속성 이름이 헷갈린다면 -template- 자리에 – auto-가 들어간다고 생각하세요~

“통제를 벗어난”이 무슨 의미일까요? 아까 이 코드 기억나시나요?

.container {
	grid-template-rows: repeat(3, minmax(100px, auto));
}

각 셀마다 최소 100px의 높이를 확보하고, 컨텐츠가 높이 100px을 넘어가면 알아서 자동으로 늘어나도록(auto) 하려고 저 코드를 썼는데, 우리가 만든 예시가 row가 3개였기 때문에 repeat 회수를 3으로 지정해 줬었지요? 그런데 row 개수를 미리 알 수 없는 경우면 어떻게 할까요? 바로 이 grid-auto-rows가 그 해결책입니다.

.container {
	grid-auto-rows: minmax(100px, auto);
}

 

이렇게 grid-auto-rows를 써주면, 굳이 횟수를 지정해서 반복할 필요 없이 “알아서” 처리됩니다. 즉, grid-template-rows로 미리 세팅해 둔 것이 없이 때문에 여기 있는 모든 row들은 grid-template-rows의 통제를 벗어난 row가 되는 것이고, 바로 grid-auto-rows가 처리를 하는 거지요! “통제를 벗어난”의 의미는 바로 이겁니다.

grid-auto-rows: auto 가 적용된 이미지
grid-auto-rows : minmax(100px, auto) 속성이 적용된 이미지

각 셀의 영역 지정

  • grid-column-start
  • grid-column-end
  • grid-column
  • grid-row-start
  • grid-row-end
  • grid-row

 

  • -ms-grid-row
  • -ms-grid-column
  • -ms-grid-row-span
  • -ms-grid-column-span

이 속성들은 Grid 아이템에 적용하는 속성으로, 각 셀의 영역을 지정합니다.
아래 그림을 보면,

1부터 4까지의 Grid 라인 번호가 매겨져 있는데요, 바로 그 번호를 이용해서 column과 row의 범위를 결정합니다. column으로 살펴보면, grid-column-start가 시작 번호, grid-column-end가 끝 번호입니다. grid-column은 start와 end 속성을 한 번에 쓰는 축약형입니다.
위의 빨간색 영역을 코드로 쓰면 아래와 같아요. 이 두 코드↓는 같은 영역을 지정합니다.

.item:nth-child(1) {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 1;
  grid-row-end: 2;
}
.item:nth-child(1) {
  grid-column: 1 / 3;
  grid-row: 1 / 2;
}

위와 같이 코드를 적용하면 영역은 아래 이미지와 같이 적용됩니다.

시작번호 / 끝번호를 지정하는 방법 외에, 몇 개의 셀을 차지하게 할 것인지를 지정해줄 수도 있어요.

.item:nth-child(1) {
  /* 1번 라인에서 2칸 */
  grid-column: 1 / span 2;
  /* 1번 라인에서 3칸 */
  grid-row: 1 / span 3;
}

여기서 잠깐 위에서 공부했던 grid-auto-columns를 다시 볼게요.
grid-auto-columns는 grid-template-columns의 통제를 받지 않는 column들의 배치를 결정하는 규칙이라고 했는데요, 이 grid-column을 이용해 ‘통제받지 않는’ column들을 만들 수 있어요.

.container {
  grid-template-columns: 50px;
  grid-auto-columns: 1fr 2fr;
}
.item:nth-child(1) { grid-column: 2; }
.item:nth-child(2) { grid-column: 3; }
.item:nth-child(3) { grid-column: 4; }
.item:nth-child(4) { grid-column: 5; }
.item:nth-child(5) { grid-column: 6; }
.item:nth-child(6) { grid-column: 7; }
/* end를 생략하면 그냥 한 칸임 */

이렇게 하면, 첫 번째 column(G)만 grid-template-columns의 통제를 받아 50px로 되고, 나머지 column들은 grid-auto-columns의 규칙에 따라 1:2의 비율이 반복됩니다.

영역 이름으로 그리드 정의 : grid-template-areas

각 영역(Grid Area)에 이름을 붙이고, 그 이름을 이용해서 배치하는 방법입니다. 정말 직관적인 방법이에요.
아래의 이미지에서 각 셀에 매칭 되는 이름을 어떤 식으로 썼는지 살펴보세요.

.container {
  grid-template-areas:
    "header header header"
    "   a    main    b   "
    "   .     .      .   "
    "footer footer footer";
}

위의 형태로 각자 차지하는 셀의 개수만큼 해당 위치에 이름을 써주면 됩니다. 각 셀마다 공백을 하나씩 넣어서 구분해주시면 되고요. header는 첫 번째 row에서 3개의 column을 차지하니 맨 위에 3번 쓴 것, 이해되시죠?
빈칸은 마침표 또는 “none”을 사용하면 되고, 마침표의 개수는 여러 개를 써도 상관없습니다.

그럼 각 영역의 이름은 어떻게 매칭할까요? 해당 아이템 요소에 grid-area 속성으로 이름을 지정해주면 됩니다!
예를 들면 아래의 코드와 같이 되겠지요.

.header { grid-area: header; }
.sidebar-a { grid-area: a; }
.main-content { grid-area: main; }
.sidebar-b { grid-area: b; }
.footer { grid-area: footer; }
/* 이름 값에 따옴표가 없는 것에 주의하세요 */

자동 배치 : grid-auto-flow

아이템이 자동 배치되는 흐름을 결정하는 속성입니다.

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(25%, auto));
  grid-template-rows: repeat(5, minmax(50px,auto));
  grid-auto-flow: dense;
}
item:nth-child(2) { grid-column: auto / span 3; }
item:nth-child(5) { grid-column: auto / span 3; }
item:nth-child(7) { grid-column: auto / span 2; }

B, E, G는 각각 셀을 3개 또는 2개를 점유하도록 설정했는데요, 그 때문에 셀에 들어갈 자리가 없어서 빈 셀들이 생겼습니다. Grid 배치의 기본 설정은 아이템이 row를 기준으로 순서대로 배치가 되다가 들어갈 자리가 없으면 그 칸은 비워두고 아래로 배치가 됩니다.
dense는 기본적으로 빈 셀을 채우는 알고리즘이며, row와 column에 따라 기준이 달라집니다.

grid-auto-flow : row ;
grid-auto-flow : column;
grid-auto-flow : dense;
grid-auto-flow : row dense;
grid-auto-flow : column&amp;amp;nbsp;dense;
 

세로 방향 정렬 : align-items

아이템들을 세로(column축) 방향으로 정렬합니다. 컨테이너에 적용합니다.

.container {
	align-items: stretch;
	/* align-items: start; */
	/* align-items: center; */
	/* align-items: end; */
}
align-items : stretch ;
 
align-items : start ;
align-items : center ;

align-items : end;

가로 방향 정렬 : justify-items

아이템들을 가로(row축) 방향으로 정렬합니다. 컨테이너에 적용합니다.

.container {
	justify-items: stretch;
	/* justify-items: start; */
	/* justify-items: center; */
	/* justify-items: end; */
}

justify-items : stretch ;

justify-items : start;
justify-items : center;
justify-items : end;

place-items

align-items와 justify-items를 같이 쓸 수 있는 단축 속성이에요.
align-items, justify-items의 순서로 작성하고, 하나의 값만 쓰면 두 속성 모두에 적용됩니다.

.container {
	place-items: center start;
}

아이템 그룹 세로 정렬 : align-content

Grid 아이템들의 높이를 모두 합한 값이 Grid 컨테이너의 높이보다 작을 때 Grid 아이템들을 통째로 정렬합니다.

.container {
	align-content: stretch;
	/* align-content: start; */
	/* align-content: center; */
	/* align-content: end; */
	/* align-content: space-between; */
	/* align-content: space-around; */
	/* align-content: space-evenly; */
}
align-content :&amp;amp;nbsp; stretch
align-content :&amp;amp;nbsp; start
align-content :&amp;amp;nbsp; center
align-content :&amp;amp;nbsp; end
align-content :&amp;amp;nbsp; space-between
align-content :&amp;amp;nbsp; space-around
align-content :&amp;amp;nbsp; space-evenly
 

아이템 그룹 가로 정렬 : justify-content

Grid 아이템들의 너비를 모두 합한 값이 Grid 컨테이너의 너비보다 작을 때 Grid 아이템들을 통째로 정렬합니다.

.container {
	justify-content: stretch;
	/* justify-content: start; */
	/* justify-content: center; */
	/* justify-content: end; */
	/* justify-content: space-between; */
	/* justify-content: space-around; */
	/* justify-content: space-evenly; */
}
justify-content :&amp;amp;nbsp; stretch
justify-content :&amp;amp;nbsp; start
justify-content :&amp;amp;nbsp; center
justify-content :&amp;amp;nbsp; end
justify-content :&amp;amp;nbsp; space-between
justify-content :&amp;amp;nbsp; space-around
justify-content :&amp;amp;nbsp; space-evenly

place-content

align-content와 justify-content를 같이 쓸 수 있는 단축 속성이에요.
align-content, justify-content의 순서로 작성하고, 하나의 값만 쓰면 두 속성 모두에 적용됩니다.

.container {
	place-content: space-between center;
}

개별 아이템 세로 정렬

  • align-self
  • -ms-grid-row-align

해당 아이템을 세로(column축) 방향으로 정렬합니다. 아이템에 적용합니다.

.item {
	align-self: stretch;
	/* align-self: start; */
	/* align-self: center; */
	/* align-self: end; */
}

align-self :&amp;amp;nbsp; stretch

align-self :&amp;amp;nbsp; start
 
align-self :&amp;amp;nbsp; center
align-self :&amp;amp;nbsp; end
 
 

개별 아이템 가로 정렬

  • justify-self
  • -ms-grid-column-align

해당 아이템을 가로(row축) 방향으로 정렬합니다. 아이템에 적용합니다.

.item {
	justify-self: stretch;
	/* justify-self: start; */
	/* justify-self: center; */
	/* justify-self: end; */
}
justify-self :&amp;amp;nbsp; stretch
justify-self :&amp;amp;nbsp; start
justify-self :&amp;amp;nbsp; center
justify-self :&amp;amp;nbsp; end

place-self

align-self와 justify-self를 같이 쓸 수 있는 단축 속성이에요.
align-self, justify-self의 순서로 작성하고, 하나의 값만 쓰면 두 속성 모두에 적용됩니다.

.item {
	place-self: start center;
}

배치 순서 : order

각 아이템들의 시각적 나열 순서를 결정하는 속성이에요.
숫자 값이 들어가며, 작은 숫자일수록 먼저 배치됩니다. "시각적" 순서일 뿐, HTML 자체의 구조를 바꾸는 것은 아니므로 접근성 측면에서 사용에 주의하셔야 합니다. 시각 장애인 분들이 사용하는 스크린 리더로 화면을 읽을 때, order를 이용해 순서를 바꾼 것은 의미가 없다는 것을 기억해 주세요.

.item:nth-child(1) { order: 3; } /* A */
.item:nth-child(2) { order: 1; } /* B */
.item:nth-child(3) { order: 2; } /* C */

z-index

z-index로 Z축 정렬을 할 수 있어요. 숫자가 클수록 위로 올라옵니다.
(position에서의 z-index랑 똑같이 생각하시면 됩니다.)

.item:nth-child(5) {
	z-index: 1;
	transform: scale(2);
}
/* z-index를 설정 안하면 0이므로, 1만 설정해도 나머지 아이템을 보다 위로 올라온다 */

끝으로, IE(인터넷 익스플로러) 10, 11에서 사용할 수 있는 Grid 속성을 알려드릴게요.
한계는 있지만, 적절히 사용하면 충분히 상용 서비스에도 적용할 수 있습니다!
IE에서 지원하는 스펙 참고

 

표준  IE
display: grid; display: -ms-grid;
grid-template-rows -ms-grid-rows
grid-template-columns -ms-grid-columns
grid-row-start -ms-grid-row
grid-column-start -ms-grid-column
grid-row: 1 / span 2;에서 span 2 대신 -ms-grid-row-span: 2
grid-column: 1 / span 2;에서 span 2 대신 -ms-grid-column-span: 2
align-self -ms-grid-row-align
justify-self -ms-grid-column-align

 

고생 많이 하셨습니다.

감사합니다.

 

출처 :

반응형
광고차단(애드블록)프로그램이나 브라우저를 사용중이시면 프로그램을 비활성화이나 블로그 주소를 예외 처리 해주시면 광고가 노출됩니다. 귀찮고 번거롭겠지만 광고 클릭은 저에게는 큰 힘이 됩니다. 🙇🏻‍♂️🙇🏻‍♀️
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)
//