복잡한 레이아웃 정복: flex & grid

ssong·2023년 3월 8일
0

HTML&CSS

목록 보기
4/6
post-thumbnail

🔍 레이아웃을 구현하는데 쓰이는 flex와 grid에 대해 알아보자

스마트폰, 패드 등 다양한 디바이스가 생기면서 다양한 크기의 화면 각각에 맞는 레이아웃을 고려해야 하는 상황이 되었다. 또한 번역으로 인해 글의 길이가 달라지기도 하는 등 1px에 따라 레이아웃이 달라질 위험이 있는 float로는 대응하기 어려운 상황이 생기기도 했다. 이 때 적용할 수 있는 속성이 flexgrid이다. 복잡할 수 있으나 보다 깔끔한 레이아웃을 잡을 수 있는 flexgrid를 같은 레이아웃을 잡는데 활용해보며 차이를 익혀보자!

flex

flex는 가로 혹은 세로와 같이 1차원적인 레이아웃을 잡는 데 용이하다. 특히 세로 정렬을 쉽게 할 수 있다는 점에서 우리를 아주 편안하게 해주는 CSS 속성이다.
그러나 큰 문제가 있는데 바로 우리를 <div> 지옥에 빠지게 하는 것이다. 배치를 하려는 요소의 부모 요소에 display: flex 값을 주어야 하기 때문인데, 따라서 복잡한 2차원적 레이아웃을 잡기 위해선 마크업이 매우 복잡해진다. 수 많은 div태그 사이에서 내가 배치하려는 요소를 감싸고 있는 태그를 찾아야 하고 또 각각 알맞는 값을 주어야 하니 무작정 flex를 쓰는 것은 재고해봐야 한다. flex가 많아질 수록 구조를 따라가기가 힘들어진다.

2차원 레이아웃을 flex를 사용해 구현하면 이렇게 일명 <div> 지옥에 빠지게된다...😱

뿐만 아니라 매우 복잡한 CSS 작업까지 기다리고 있다.🫥

flex 아이템 원하는 비율로 분할하기 - flex-basis/flex-grow

flex를 사용해 요소를 원하는 비율로 배치하기 위해서는 flex-basisflex-grow를 사용해주면 된다.
flex-basis
flex-basisflex 아이템의 기본 너비를 설정한다. flex-direction에 따라 주축 방향에 해당하는 너비를 flex-basis로 설정할 수 있다. (row일 땐 width, column일 땐 height)
flex-grow
flex-growflex 아이템이 flex-basis에서 설정한 값보다 커질 수 있는지를 결정한다. 컨테이너 내부에서 할당할 수 있는 공간의 정도를 지정하는데, 모든 요소가 flex-grow: 1을 가지면 1:1:1... 비율로 자리를 차지하고 그 중 한 요소가 flex-grow: 2라면 2:1:1...의 비율로 자리를 차지하게 되는 식이다.
결론은
✔️ flex-basis 값이 있다면 여백 너비를 flex-grow에 지정된 값으로 비율을 나눈다. 그렇기 때문에 여백이 아닌 전체 너비를 비율로 나누기 위해서는 flex-basis 값으로 0을 주어야 한다. flex-basis: 0인 경우는 기본적으로 점유하고 있는 너비가 0이라는 의미이기 때문이다.

gap을 주지 않으면 위와 같이 깔끔히 해결되지만 gap을 줄 경우 gap 값을 제외한 너비에서 비율을 따지게 되기 때문에 이를 반영해 계산하는 과정까지 거쳐야 한다.

벌써부터 머리가 복잡해진다. 어떻게 하면 쉽게 2차원 레이아웃을 구현할 수 있을까?

grid

행과 열 두 방향으로 레이아웃을 배치하는 아주아주 편리한 방법이 있으니 바로 grid이다. 배치할 요소들의 부모 요소에 display값을 주어야 하는 것은 똑같지만 div지옥에는 빠지지 않는다. 행과 열의 크기를 지정해 생성한 grid-cellgrid-item을 배치하는 방식이기에 <div>로 묶어줄 필요가 없다.

.container {
  display: grid;
  grid-template-columns: 2fr 1fr 2fr;
  grid-template-rows: repeat(3, 1fr);
}

grid-track 사이즈 지정하기

grid-track의 사이즈를 지정하는 grid-template-columnsgrid-template-rows에 활용할 수 있다
fr
fr은 fraction의 약자로 grid-container 안에서 grid-track의 비율을 지정해줄 수 있는 단위다. px를 활용해 고정된 값을 줄 수 있지만 유연한 길이 단위인 fr을 사용하면 반응형에도 대응할 수 있어 편리하다.
repeat
반복되는 값이 올 때 사용할 수 있는 함수로 repeat(반복 횟수, 값)을 적어주면 된다.
minmax
최소와 최대 사이의 범위를 지정하는 함수로 minmax(최솟값, 최댓값)으로 적어주면된다. minmax(최솟값, auto)와 같이 최솟값만 지정하고 값이 상황에 따라 늘어나게 처리해줄 수 있다.


개발자 모드에서 grid 버튼을 누르면

이와 같이 grid 배치를 확인할 수 있다.

이렇게 생성된 그리드 셀의 집합인 그리드 에어리어 값을 설정하고 이를 그리드 아이템과 매칭시키는 것으로 배치를 끝낼 수 있다.

이 간단해진 코드를 보라!

grid 영역 지정하기

grid 영역을 지정하기 위한 방법으론 두 가지가 있다.
1. grid-line으로 각 셀 영역 지정
grid-line의 번호를 활용해 grid-item이 차지하는 영역을 지정하는 방식으로 grid-column-start, grid-column-end, grid-row-start, grid-row-end로 범위의 시작과 끝을 지정할 수 있으며 grid-column, grid-row와 같이 단축 속성으로도 사용된다. grid-area로 한 번에 설정할 수도 있다.
2. grid-area 이름 지정
grid-template-areas를 통해 grid-area의 이름을 붙여 이를 지정하는 보다 직관적인 방식으로 차지하는 grid-cell의 범위만큼 같은 이름을 설정한 후 각 grid-itemgrid-area에 이름을 매칭해 적어주면 되는 방식이다.
위의 예시 코드에서 이 방법을 활용했다.


이건 grid로 짠 줄 알았는데...?

grid로 레이아웃을 짜는 것에 편안함을 느낀 후 실제로 grid를 사용한 웹페이지를 확인하고 싶었다. 이 부분은 grid를 활용하면 편하겠다! 라고 생각하고 개발자 도구를 켜보면

flex도 아닌 심지어 float로...!!😮

네이버나 다음과 같은 큰 IT 기업에서 왜 새로운 기술을 쓰지 않는 건지 의문을 가질 수 있지만 네이버, 다음 등 포털 사이트는 이용자가 매우 다양하다는 사실을 기억해야 한다. 그렇기에 모든 브라우저에서 대응 가능한 코드를 짜야한다.

갈 수록 늘어가는 빨간 블록들

float를 선택한 이유는 여기에 있다. 특히 grid는 아무래도 웹접근성 측면에서 좋은 선택은 아니다.

➕ 그렇다면 grid를 쓰는 실제 사례를 찾아 볼 수는 없는 것일까? 찾아보던 중 애플 공식 홈페이지에서 grid를 사용한 것을 확인했다!


flex로만 레이아웃을 구성해왔던 것이 억울해진(?) 순간이었다. grid도 물론 처음 접한 용어도 많고 깊게 팔수록 복잡해지지만 잘 활용하면 쉽게 레이아웃을 구성할 수 있다는 점에서 매우 매력적이다. 다양한 속성을 숙지해 활용할 수 있도록 해야겠다.

참고자료
https://flexngrid.com/
https://studiomeal.com/archives/197
https://studiomeal.com/archives/533

0개의 댓글