기존에 사용하던 레이아웃 기법은 display, float, position으로 컬럼 레이아웃을 표현하는 데 한계가 있고 구현 방법이 복잡한 문제가 있었는데요. 마크업 개발자들이 종종 “이것은 구현이 어렵습니다.” 라고 얘기했던 이유 중 하나이기도 했습니다.
flexbox 모델의 장점을 한 마디로 표현하면 “복잡한 계산 없이 박스의 크기와 순서를 유연하게 배치할 수 있다.” 라고 정리할 수 있습니다. 정렬, 방향, 순서, 사이즈 등을 유연하게 조절하기 때문에 별도의 분기 처리가 줄어들고, CSS만으로 다양한 레이아웃 구현이 가능합니다. PC는 IE10이상 대응시, 모바일에서는 Android, IOS 거의 모든 버전에서 적용이 가능합니다. (https://caniuse.com/#feat=flexbox)
기존 작업방식과 차이점을 중심으로 각 레이아웃에 대해 하나씩 살펴보도록 하겠습니다.
예제
URL : https://codepen.io/witblog/full/rrGjPx
- 스크롤이 없는 100% 레이아웃
- 네비게이션
- 바닥에 붙는 푸터
- 중앙정렬 아이콘
- 유동 너비 박스
- 말줄임 + 아이콘들
- 상하 정렬 롤링 리스트
- 정렬이 다른 메뉴
- 폼 타이틀 수직중앙정렬
- 가로세로 비율을 유지하는 반응형 박스
1. 스크롤이 없는 100% 레이아웃
부동산 PC 개편 레이아웃은 싱글 페이지 레이아웃으로 구성되어 있습니다.
페이지 전체에는 스크롤이 없는 형태로, 영역 내부에서만 스크롤이 생성됩니다.
기존에 flex 속성을 쓰지 않은 경우에는 html 최상위에서부터 height: 100%를 주면서 상속받게 하고,
하위 영역들에는 height: calc(100% – 60px)과 같이 계산해서 지정해주는 방식으로 적용하였습니다.
또는 일정 padding을 주면서 margin을 음수로 주면서 맞추기도 하였습니다.
flex 속성을 쓰면 100% 높이 지정의 번거로움에서 벗어날 수 있습니다.
전체 래퍼(.wrap
)에 absolute를 주어 고정하고 width, height를 100%로 잡아줍니다.
flex 속성에서 flex-direction 속성은 기본 값이 row이기 때문에 수직으로 적용하기 위해, column으로 변경하였습니다.
.wrap { display: flex; flex-direction: column; position: absolute; width: 100%; height: 100%; }
상단 header 영역은 고정 height 값을 주었고, .map_wrap
영역에는 flex: 1
값을 주어 확장되도록 하였습니다.
flex 아이템을 다시 flex 컨테이너로 만들어(display: flex) 하위 요소인 .map
에서도 다시 flex: 1
을 주었습니다.
.map_wrap { flex: 1; /* flex: 0 0 1 */ display: flex; } .map { flex: 1; }
flex: none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’>
기본 값 = flex: 0 1 auto
none = flex: 0 0 auto와 같다.
auto = flex: 1 1 auto와 같다.
initial = flex: 0 1 auto와 같다.
정수 = flex: 정수 1 0과 같다.
작업하면서 궁금했던 부분이 flex-basis가 auto일 때와 0일 때의 차이점이었는데요,
auto인 경우에는 컨텐츠 길이에 따라 영향을 받는다는 것을 알 수 있었습니다.
2. 네비게이션
네비게이션과 같이 왼쪽에 일부 내용을 표시하고 나머지 내용은 오른쪽에 나타낼 때, 기존에는 float 또는 absolute를 사용했었습니다.
그러기 위해서는 float을 해제하거나 부모에 relative를 주어야 하는 등 추가 작업이 필요했습니다.
플렉스 아이템에 margin: auto 속성을 주면 이 레이아웃을 간단하게 표현할 수 있습니다.
.header { display: flex; } .logo, .search, .gnb { flex: 0 0 auto; /* flex:none */ } .gnb { margin-left: auto; } .search { display: flex; } input { flex: 1; }
margin: auto
를 사용하면 auto 값을 갖는 방향(왼쪽, 오른쪽 또는 양쪽 모두)으로 빈 공간을 채우게 됩니다.
자동마진에 대한 자세한 내용은 “Flexbox 이해: 당신이 알아야 할 모든 것” 글에서 자세히 설명되어 있으니 참고해주세요.
logo, search, gnb 영역은 고정 width 값을 가지므로 grow, shrink 값을 0으로 고정하였습니다.
검색 영역에서도 input이 좌측으로 체워질 수 있도록 flex:1을 주었습니다.
3. 바닥에 붙는 푸터
컨텐츠 높이가 짧을 때에도 푸터가 아래로 붙는 레이아웃의 경우,
플렉스 아이템에 margin-top: auto
를 적용하면, 별도의 min-height를 잡지않아도 브라우저 높이만큼을 잡을 수 있게 됩니다.
main { display: flex; } footer { margin-top: auto; }
4. 중앙정렬 아이콘
아이콘 중앙정렬은 table, absolute, transform 속성 등의 여러가지 방법으로 구현가능 하지만,
flex layout 내부의 요소에는 간단하게 margin: auto 속성을 통해 중앙 정렬을 만들 수 있습니다.
또는 flex 컨테이너에 justify-content, align-items를 중앙으로 배치하는 방법으로도 가능합니다.
.item_list { display: flex; } .icon { margin: auto; }
.item_list { display: flex; justify-content: center; align-items: center; }
5. 유동 너비 박스
부동산 필터 박스는 컨테이너 길이 및 컨텐츠의 길이에 따라 유동적인 박스입니다.
flex 아이템의 기본 값을 적용하여 기본적으로 컨텐츠 길이에 맞게 배치되고, 컨테이너의 길이가 짧을 경우에는 줄어들 수 있도록 하였습니다.
.filter { display: flex; } .filter_box { flex: 0 1 auto; /* flex 기본 값 */ max-width: 300px; ... }
마크업 순서와 관계없이, 보여지는 순서를 변경을 해야할 경우는 order 속성을 적용할 수도 있습니다.
.filter_box:nth-child(3) { order: -1; }
order 기본 값 : 0
값이 낮을 수록 앞으로 위치
6. 말줄임 + 아이콘들
기존에 우측에 아이콘이 유동적으로 붙는 컨텐츠의 말줄임을 구현하려면 float과 overflow 속성을 활용했습니다.
float에 인접한 요소에 overflow: hidden
을 주면 아이콘의 개수에 관계없이 유동적으로 100%를 채울 수 있었기 때문인데요,
이 속성은 순서상 float이 꼭 우선 적용되어야 가능한 레이아웃이기 때문에 순서가 뒤바뀌는 이슈가 있었습니다.
inline-flex 속성을 활용하면 순서대로 적용할 수 있습니다.
inline-flex는 inline-block과 유사하게 inline-level로 배치되면서, 내부에서 flex container를 생성합니다.
<div class="title_wrap"> <h3 class="title">조건에 맞는 총10000000000000개의매물이있습니다.</h3> <span class="school_type" role="img" aria-label="가정"><i class="sp_icon"></i></span> <span class="school_type" role="img" aria-label="통학차량"><i class="sp_icon"></i></span> <span class="school_type" role="img" aria-label="공립"><i class="sp_icon"></i></span> </div>
.title_wrap { display: inline-flex; max-width: 100%; } .title { flex: 1; }
7. 상하 정렬 롤링 리스트
normal flow에 따라 inline level elements는 왼쪽에서 오른쪽으로 하나씩 쌓이다가, 부모의 width를 넘어가면
다음 줄로 넘어가서 왼쪽에서 오른쪽으로 쌓이는 흐름을 가지고 있습니다.
여기서 normal flow의 우선순위는 좌우가 더 먼저이고, 좌우 흐름을 따를 수 없을 때 상하 흐름을 따른다는 것을 알 수 있습니다.
하지만 box가 쌓이는 순서의 흐름이 좌우 보다 상하가 더 우선시되는, normal flow에서 벗어난 UI도 있습니다.
2행 이상의 상하 정렬 리스트가 대표적인 예입니다.
위 그림과 같은 순서를 만들기 위해서는 세로영역에 있는 리스트들을 부모로 한 번 더 감싸줘야합니다.
그렇게 되면 depth가 깊어지게 되고, UI가 변경 됐을 때 해당 부모영역도 수정해야합니다.
flex-direction의 column 속성 값을 이용하면 부모영역으로 감싸지 않고도 위의 흐름을 표현할 수 있습니다.
.photo_container { overflow: hidden; } .photo_list { display: flex; height: 500px; flex-flow: column wrap; align-content: flex-start; } .photo_box { flex: 0 0 206px; }
align-items 기본 값: stretch
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
flex-wrap 기본 값: nowrap
8. 정렬이 다른 메뉴
라인TV 모바일웹의 탭 메뉴는 좌우 텍스트 정렬이 다르게 들어가는 레이아웃입니다.
기존에는 가장 왼쪽과 오른쪽에 있는 메뉴에 각각 text-align의 속성 값인 left와 right를 주어 양끝에 붙도록 만들었고,
중앙 메뉴에는 center 값을 주었습니다.
하지만 flex를 이용하면 메뉴 각각마다 text-align 속성 값을 다르게 줄 필요없이
justify-content 속성만으로 아래 레이아웃을 구현할 수 있습니다.
.tablist { display: flex; justify-content: space-between; }
9. 폼 타이틀 수직중앙정렬
폼요소에서 한글 텍스트는 한 줄로 노출되지만, 영어 텍스트는 두 줄이 노출되는 경우가 있습니다.
flex와 align-items의 center속성 값을 이용하면 텍스트가 한 줄이든지 여러 줄이든지 상관없이 중앙정렬을 할 수 있습니다.
.title { display: flex; align-items: center; }
10. 가로세로 비율을 유지하는 반응형 박스
라인TV 모바일웹에서는 디바이스 해상도에 따라 크기가 달라지는 반응형 박스를 사용합니다.
.item의 width 값을 %로 주고, <img>
의 width와 height를 100%로 줘서 반응형 박스를 만들었습니다.
하지만 .item 내부에 <img>
가 없을 때 .thumb의 height가 0이 되어버리는 문제가 생겼습니다.
이를 해결하기 위해 .thumb:before에 padding-top의 속성값으로 이미지 세로비율에 해당하는 %를 할당하여,<img>
가 없더라도 height가 유지될 수 있도록 했습니다.
하지만 이러한 방식은 이미지 크기가 변경되면 가로세로 비율을 다시 계산하여 padding-top 속성값을 바꿔줘야한다는 번거로움이 따릅니다.
flex를 사용하여 위의 반응형 박스를 구현하면, <img>
가 없을 때 가상요소로 padding-top을 주지 않아도 해당 영역이 유지됩니다.
.title
의 flex: none와 flex-basis: 34px를 축약해서 flex: 0 0 34px
로 쓸 수 있지만, 의도를 더 명확하게 나타내기 위해 flex: none를 사용하였습니다. flex-basis값을 우선 적용하기 위해 min-height는 0으로 설정해주었습니다.
.channel_list { display: flex; flex-flow: wrap column; } .item { display: flex; flex-direction: column; flex: 1 1 33.3%; } .thumb { flex: 1 1 0; } .title { flex: none; flex-basis: 34px; min-height: 0; }
참고링크
- A Complete Guide to Flexbox https://css-tricks.com/snippets/css/a-guide-to-flexbox/
- CSS flexible 레이아웃 http://naradesign.net/wp/2017/04/20/2363/
- flexbox의 전형적인 사용 https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Typical_Use_Cases_of_Flexbox
- Flexbox 이해- 당신이 알아야 할 모든 것 https://www.vobour.com/4-flexbox-이해-당신이-알아야-할-모든-것-understa
- flexbox 스펙을 읽으면서 배운 11가지 것들 http://wiki.navercorp.com/pages/viewpage.action?pageId=344322322
마치며
flexbox 속성이 나온지는 꽤 되었지만, 이론적으로만 접하고 실무에서 적용하기 쉽지 않았던 것이 사실입니다.
PC에서도 서비스별 브라우저 대응이 업그레이드(IE10이상) 되어서, 장점이 많은 flexbox를 다양하게 활용할 수 있었으면 좋겠습니다.
궁금한 점이 있으시거나 다른 좋은 사례들이 있다면 알려주세요. 감사합니다.
0개의 댓글