🔍 레이아웃을 구현하는데 쓰이는 flex와 grid에 대해 알아보자
스마트폰, 패드 등 다양한 디바이스가 생기면서 다양한 크기의 화면 각각에 맞는 레이아웃을 고려해야 하는 상황이 되었다. 또한 번역으로 인해 글의 길이가 달라지기도 하는 등 1px에 따라 레이아웃이 달라질 위험이 있는 float
로는 대응하기 어려운 상황이 생기기도 했다. 이 때 적용할 수 있는 속성이 flex
와 grid
이다. 복잡할 수 있으나 보다 깔끔한 레이아웃을 잡을 수 있는 flex
와 grid
를 같은 레이아웃을 잡는데 활용해보며 차이를 익혀보자!
flex
flex
는 가로 혹은 세로와 같이 1차원적인 레이아웃을 잡는 데 용이하다. 특히 세로 정렬을 쉽게 할 수 있다는 점에서 우리를 아주 편안하게 해주는 CSS 속성이다.
그러나 큰 문제가 있는데 바로 우리를 <div>
지옥에 빠지게 하는 것이다. 배치를 하려는 요소의 부모 요소에 display: flex
값을 주어야 하기 때문인데, 따라서 복잡한 2차원적 레이아웃을 잡기 위해선 마크업이 매우 복잡해진다. 수 많은 div
태그 사이에서 내가 배치하려는 요소를 감싸고 있는 태그를 찾아야 하고 또 각각 알맞는 값을 주어야 하니 무작정 flex
를 쓰는 것은 재고해봐야 한다. flex
가 많아질 수록 구조를 따라가기가 힘들어진다.
2차원 레이아웃을 flex
를 사용해 구현하면 이렇게 일명 <div>
지옥에 빠지게된다...😱
뿐만 아니라 매우 복잡한 CSS 작업까지 기다리고 있다.🫥
flex 아이템 원하는 비율로 분할하기 -
flex-basis
/flex-grow
flex
를 사용해 요소를 원하는 비율로 배치하기 위해서는flex-basis
와flex-grow
를 사용해주면 된다.
flex-basis
flex-basis
는flex
아이템의 기본 너비를 설정한다.flex-direction
에 따라 주축 방향에 해당하는 너비를flex-basis
로 설정할 수 있다. (row
일 땐width
,column
일 땐height
)
flex-grow
flex-grow
는flex
아이템이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-cell
에grid-item
을 배치하는 방식이기에 <div>
로 묶어줄 필요가 없다.
.container {
display: grid;
grid-template-columns: 2fr 1fr 2fr;
grid-template-rows: repeat(3, 1fr);
}
grid-track
사이즈 지정하기
grid-track
의 사이즈를 지정하는grid-template-columns
와grid-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-item
에grid-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