[CSS] flex에 대해 알아보기
CSS FLEX 의 기본 개념과 학습법을 익히고 이를 활용해 보는 방법을 배워 보자
1. 개요
FLEX 란 레이아웃을 위해 탄생한 CSS 속성입니다.
FLEX를 알아보기 위해 layout 의 역사부터 살펴볼까요?
1-1. layout 의 역사
초창기 html css 가 나왔을 때만 해도 layout 은 table 태그로 잡는 것이 일반화 되었던 시절이 있었습니다.
하지만 html은 문서이고 각각의 TAG는 의미를 담고 있기때문에 table은 레이아웃을 잡기에는 의미도 명확하지 않을 뿐만 아니라 html 문서 코딩양에도 많은 문제점들이 야기 되었습니다.
그후에는 float을 이용한 레이아웃을 많이 활용하고 있었는데 이는 위치 계산값 그리고 흔히 말하는 성배레이아웃을 나타낼시 컨텐츠의 크기 처리가 어려워 지는 이슈들이 발생하였습니다.
그와중에 flex 가 발표되면서 이러한 레이아웃을 다루는것이 비교적 쉬워졌고 grid 라는 속성까지 발표함으로써 레이아웃을 잡기가 더욱 용이 해 졌습니다.
[성배레이아웃]
1-2 flex의 소개 및 기본 구조
1-2-1 flex 소개
Flex(플렉스)는 Flexible Box, Flexbox라고 부르기도 합니다.
Flex는 레이아웃 배치 전용 기능으로 고안되었습니다. 그래서 앞서서 소개했던 레이아웃을 만들 때 딱히 사용할게 없어서 쓰던 float나 inline-block 등을 이용한 기존 방식보다 훨씬 강력하고 편리한 기능들이 많이 지원됩니다.
[Flex에 관한 오해]
“Grid가 나온 이상, Flex는 구시대의 유물일 뿐이다.”
저는 아니라고 생각합니다. 더 나중에 나온 스펙인 Grid로도 Flex와 똑같이 구현할 수 있는 경우가 많지만, Grid로는 구현이 어려운 레이아웃이거나 Flex를 쓰는게 더 편리한 경우도 있습니다. 그리고 마소가 싼 똥 버렸지만 우리는 여전히 지원해줘야 하는 인터넷 익스플로러(IE)같은 경우는 Flex는 표준 스펙을 지원하지만 Grid는 legacy(고인물) 버전만 지원하기 때문에, 둘 다 잘 알아두고 적재적소에 활용하는 것이 가장 좋다고 생각됩니다..
1-2-2 flex의 기본구조
flex는 부모요소와 자식요소 이렇게 계층구조로 나타나 있습니다.
부모요소는 Flex Container 라고 불리며 자식요소는 Flex Item 라고 불립니다.
<div class="container">
<div class="item">item1</div>
<div class="item">item2</div>
<div class="item">item3</div>
</div>
다시 말해서 flex는 위의 코드와 같이 부모 자식요소들이 있으며 부모에게 지정해줘야 할 속성과 자식 요소에게 지정해줘야 할 속성들이 각각 있으며 그 역할을 이렇게 생각 하시면 됩니다.
“컨테이너가 Flex의 영향을 받는 전체 공간이고 설정된 속성에 따라 각각의 아이템들이 어떠한 형태로 배치되는것” 이라고 말이죠.
2. Flex 속성
flex 속성은 [1-2-2 flex의 기본구조]절에서 설명했던것과 같이 2개의 분류로 나눌 수 있습니다.
- 컨테이너에 적용하는 속성
- 아이템에 적용하는 속성
이중 컨테이너에 적용하는 속성에 대해서 알아보도록 하겠습니다.
2-1. Flex Container 속성
속성 | 의미 |
---|---|
display | Flex Container를 정의 |
flex-flow | flex-direction과 flex-warp의 단축 속성 |
flex-direction | Flex Items의 주 축(main-axis)을 설정 |
flex-wrap | Flex Items의 여러 줄 묶음(줄 바꿈) 설정 |
justify-content | 주 축(main-axis)의 정렬 방법을 설정 |
align-content | 교차 축(cross-axis)의 정렬 방법을 설정(2줄 이상) |
align-items | 교차 축(cross-axis)에서 Items의 정렬 방법을 설정(1줄) |
2-1-1. display
display 속성으로 Flex Container를 정의합니다.
보통 요소의 표시 방법을 display: block;, display: inline-block 혹은 display: none; 같이 사용하는 경우가 많죠.
같은 요소의 표시 방법으로 Block이나 Inline이 아닌 Flex(display: flex, display: inline-flex)로 정의합니다.
값 | 의미 | 기본값 |
---|---|---|
flex | Block 특성의 Flex Container를 정의 | |
inline-flex | Inline 특성의 Flex Container를 정의 |
flex 와 inline-flex는 차이는 단순합니다.
display: flex;로 지정된 Flex Container는 Block 요소와 같은 성향(수직 쌓임)을 가지며,
display: inline-flex로 지정된 Flex Container는 Inline(Inline Block) 요소와 같은 성향(수평 쌓임)을 가집니다.
[그림 2-1-1. display]
위의 그림을 보시면 컨테이너의 쌓임을 주목하셔서 보시면 될 것 같습니다. 수직쌓임과 수평쌓임의 개념을 이해해주세요
그럼 예제로 살펴볼까요?
See the Pen 2021-05-01-css-flex by Jung Hun (@manbalboy) on CodePen.
다음 코드팬을 실행하면 다음과 같은 결과가 나옵니다.
무엇이든지 반복 학습이 제일 중요합니다. 직접 codepen code를 복사해서 실습해보세요
2-1-2. flex-flow
이 속성은 단축 속성으로 Flex Items의 주 축(main-axis)을 설정하고 Items의 여러 줄 묶음(줄 바꿈)도 설정합니다.
.flex-container {
flex-flow: row-reverse wrap;
}
위의 속성에서 값이 row-reverse wrap 와 같이 띄어쓰기로 나누어진 것을 볼 수 있습니다.
앞의 속성값이 flex-directiion ,뒤의 속성값이 flex-wrap 를 의미합니다.
값 | 의미 | 기본값 |
---|---|---|
flex-direction | Items의 주 축(main-axis)을 설정 | row |
flex-wrap | Items의 여러 줄 묶음(줄 바꿈) 설정 | nowrap |
각각의 속성들을 살펴 볼까요?
2-1-2-1. flex-direction
item의 메인축을 설정하는 속성입니다.
값 | 의미 | 기본값 |
---|---|---|
row | Itmes를 수평축(왼쪽에서 오른쪽으로)으로 표시 | row |
row-reverse | Items를 row의 반대 축으로 표시 | |
column | Items를 수직축(위에서 아래로)으로 표시 | |
column-reverse | Items를 column의 반대 축으로 표시 |
위의 장표에서 row를 이해하기 쉽게 수평축이라고 설명하였는데 row를 사실 글쓰기방향 column을 글쓰기방향의 수직축이라고 이해하셔야 정확한 이해입니다.
한국어랑 영어는 글쓰기방향이 가로방향으로 글쓰기를 하지만 중국어나 히브리어같은 경우는 위에서 아래로 수직방향으로 글쓰기를 하기 때문에 writing-mode: vertical-lr; 라는 속성을 주면 수평축과 수직축이 바뀌어 당황하실 수 있습니다.
하지만 저희는 영어권이나 한국 사이트 위주로 개발하기 때문에 대부분의 설명도 row는 수평축 column은 수직축이라고 설명된 문서들이 많습니다.
그럼 코드로 이해해볼까요?
See the Pen 2021-05-01-css-flex-direction by Jung Hun (@manbalboy) on CodePen.
위의 코드를 실행해 보셨나요? 결과는 다음과 같습니다.
같은 코드를 글쓰기방향을 바꾸어서 실행해보세요. writing-mode: vertical-lr; 속성만 추가하시면 됩니다.
See the Pen 2021-05-01-css-flex-direction01 by Jung Hun (@manbalboy) on CodePen.
여기까지 flex-direction에 대해서 알아 보았는데요 여기서 앞으로 설명할 속성들을 배우기 앞서 용어 몇가지를 소개하고 넘어 가겠습니다.
주 축(main-axis)과 교차 축(cross-axis)
주 축 이란 앞서 설명한 글쓰기 방향이라고 생각 하시면 되고 교차 측 은 글쓰기의 수직축 이라고 생각하시면 됩니다.
시작점(flex-start)과 끝점(flex-end)
시작점(flex-start)과 끝점(flex-end)이라는 개념도 있습니다.
이는 주 축이나 교차 축의 시작하는 지점과 끝나는 지점을 지칭합니다.
역시 방향에 따라 시작점과 끝점이 달라집니다.
2-1-2-2. flex-wrap
|값|의미|기본값| |:—|:—|:—| |nowrap|모든 Itmes를 여러 줄로 묶지 않음(한 줄에 표시)|nowrap| |wrap|Items를 여러 줄로 묶음|| |wrap-reverse|Items를 wrap의 역 방향으로 여러 줄로 묶음||
기본적으로 Items는 한 줄에서만 표시되고 줄 바꿈 되지 않습니다. 이는 지정된 크기(주 축에 따라 width나 height)를 무시하고 한 줄 안에서만 가변합니다. Items를 줄 바꿈 하려면 값으로 wrap을 사용해야 합니다.
이제 코드로 알아볼까요?
See the Pen 2021-05-01-css-flex-wrap by Jung Hun (@manbalboy) on CodePen.
위의 코드를 실행해 보면 줄바꿈이 어떠한 이야기 인지 이해 하셨으리라 믿습니다.
2-1-3. justify-content
주 축(main-axis)의 정렬 방법을 설정합니다.
값 | 의미 | 기본값 |
---|---|---|
flex-start | Items를 시작점(flex-start)으로 정렬 | flex-start |
flex-end | Items를 끝점(flex-end)으로 정렬 | |
center | Items를 가운데 정렬 | |
space-between | 시작 Item은 시작점에, 마지막 Item은 끝점에 정렬되고 나머지 Items는 사이에 고르게 정렬됨 | |
space-around | Items를 균등한 여백을 포함하여 정렬 |
각각 속성값의 따라 위의 그림과 같이 배치됩니다.
2-1-3. align-content
교차 축(cross-axis)의 정렬 방법을 설정합니다.
주의할 점은 flex-wrap 속성을 통해 Items가 여러 줄(2줄 이상)이고 여백이 있을 경우만 사용할 수 있습니다.
값 | 의미 | 기본값 |
---|---|---|
stretch | Container의 교차 축을 채우기 위해 Items를 늘림 | stretch |
flex-start | Items를 시작점(flex-start)으로 정렬 | |
flex-end | Items를 끝점(flex-end)으로 정렬 | |
center | Items를 가운데 정렬 | |
space-between | 시작 Item은 시작점에, 마지막 Item은 끝점에 정렬되고 나머지 Items는 사이에 고르게 정렬됨 | |
space-around | Items를 균등한 여백을 포함하여 정렬 |
각각 속성값의 따라 위의 그림과 같이 배치됩니다.
2-1-4. align-items
교차 축(cross-axis)에서 Items의 정렬 방법을 설정합니다. Items가 한 줄일 경우 많이 사용합니다.
주의할 점은 Items가 flex-wrap을 통해 여러 줄(2줄 이상)일 경우에는 align-content 속성이 우선합니다.
따라서 align-items를 사용하려면 align-content 속성을 기본값(stretch)으로 설정해야 합니다
값 | 의미 | 기본값 |
---|---|---|
stretch | Container의 교차 축을 채우기 위해 Items를 늘림 | stretch |
flex-start | Items를 각 줄의 시작점(flex-start)으로 정렬 | |
flex-end | Items를 각 줄의 끝점(flex-end)으로 정렬 | |
center | Items를 가운데 정렬 | |
baseline | Items를 문자 기준선에 정렬 |
각각 속성값의 따라 위의 그림과 같이 배치됩니다.
2-2 Flex Items 속성
이번엔 Flex Items 요소에 대해서 알아볼까요?
속성 | 의미 |
---|---|
order | Flex Item의 순서를 설정 |
flex | flex-grow, flex-shrink, flex-basis의 단축 속성 |
flex-grow | Flex Item의 증가 너비 비율을 설정 |
flex-shrink | Flex Item의 감소 너비 비율을 설정 |
flex-basis | Flex Item의 (공간 배분 전) 기본 너비 설정 |
align-self | 교차 축(cross-axis)에서 Item의 정렬 방법을 설정 |
그럼 각각 속성에대해 상세히 살펴볼까요?
2-2-1. order
Item의 순서를 설정합니다.
Item에 숫자를 지정하고 숫자가 클수록 순서가 밀립니다.
음수가 허용됩니다.
HTML 구조와 상관없이 순서를 변경할 수 있기 때문에 유용합니다.
값 | 의미 | 기본값 |
---|---|---|
숫자 | Item의 순서를 설정 | 0 |
그럼 코드를 통해 알아보겠습니다.
See the Pen 2021-05-01-css-flex-order by Jung Hun (@manbalboy) on CodePen.
위의 코드를 실행 시키면 order 별로 아이템이 배치되는것을 보실수 있습니다.
2-2-2. flex
flex 속성은 Item의 너비(증가, 감소, 기본)를 설정하는 단축 속성입니다.
값 | 의미 | 기본값 |
---|---|---|
flex-grow | Item의 증가 너비 비율을 설정 | 0 |
flex-shrink | Item의 감소 너비 비율을 설정 | 1 |
flex-basis | Item의 (공간 배분 전) 기본 너비 설정 | auto |
flex-grow를 제외한 개별 속성은 생략할 수 있습니다.
만약 flex: 1; 로 작성하면 flex-grow: 1;과 같습니다.
그러면 나머지 속성은 생략했으니 기본값이 적용되어 flex-shrink: 1;, flex-basis: auto;가 되겠죠?
즉 flex: 1; 혹은 flex: 1 1;은 flex: 1 1 auto;와 같다고 볼 수 있습니다만 그렇지 않습니다.
flex-basis의 기본값은 auto입니다만 단축 속성인 flex에서 그 값을 생략할 경우 0이 적용됩니다.
다시 정리하면 flex: 1; 혹은 flex: 1 1;은 flex: 1 1 0;이 된다는 것입니다.
이 부분을 기억하지 않으면 엉뚱한 결과가 나올 수 있으니 주의합시다!
flex-basis 단축 속성을 생략하면 기본값이 0
그럼 각각의 속성들을 살펴보겠습니다.
2-2-2-1. flex-grow
Item의 증가 너비 비율을 설정합니다.
숫자가 크면 더 많은 너비를 가집니다.
Item이 가변 너비가 아니거나, 값이 0일 경우 효과가 없습니다.
값 | 의미 | 기본값 |
---|---|---|
숫자 | Item의 증가 너비 비율을 설정 | 0 |
모든 Items의 총 증가 너비(flex-grow)에서 각 Item의 증가 너비의 비율 만큼 너비를 가질 수 있습니다.
예를 들어 Item이 3개이고 증가 너비가 각각 1, 2, 1이라면,
첫 번째 Item은 총 너비의 25%(1/4)을,
두 번째 Item은 총 너비의 50%(2/4)를,
세 번째 Item은 총 너비의 25%(1/4)을 가지게 됩니다.
쉽게 말해서 총합을 비율로 나눈값이라고 보시면 됩니다.
코드로 살펴보겠습니다
See the Pen flex-grow by Jung Hun (@manbalboy) on CodePen.
창의 크기에 따라 비율이 달라지는것을 보실 수 있습니다.
2-2-2-2. flex-shrink
Item이 감소하는 너비의 비율을 설정합니다.
숫자가 크면 더 많은 너비가 감소합니다.
Item이 가변 너비가 아니거나, 값이 0일 경우 효과가 없습니다.
값 | 의미 | 기본값 |
---|---|---|
숫자 | Item의 감소 너비 비율을 설정 | 0 |
감소 너비(flex-shrink)는 요소의 너비에 영향을 받기 때문에 계산하기 까다롭습니다.
영향을 받는다는 요소의 너비는 width, height, flex-basis 등으로 너비가 지정된 경우를 의미합니다.
Container의 너비가 줄어 Items의 너비에 영향을 미칠 경우, 영향을 미치기 시작한 지점부터 줄어든 거리 만큼 감소 너비 비율에 맞게 Item의 너비가 줄어듭니다.
예를 들어 Container의 너비가 줄어 Item의 너비에 영향을 미치기 시작한 지점부터 실제 줄어든 거리가 90px일 때, 요소 너비가 같은 Item이 2개이고 지정된 감소 너비가 각각 2와 1이라면,
감소 너비는 2:1 비율이며,
첫 번째 Item은 90px의 2/3인 60px 만큼 너비가 감소하고,
두 번째 Item은 90px의 1/3인 30px 만큼 너비가 감소합니다.
다른 예시로 Container의 너비가 줄어 Item의 너비에 영향을 미치기 시작한 지점부터 실제 줄어든 거리가 90px일 때,
요소 너비가 다른 Item이 2개이고 요소 너비는 각각 200과 100이고,
지정된 감소 너비가 각각 2와 1이라면,
200 x 2 = 400과 100 x 1 = 100 즉 감소 너비는 4:1 비율이며,
첫 번째 Item은 90px의 4/5인 72px 만큼 너비가 감소하고,
두 번째 Item은 90px의 1/5인 18px 만큼 너비가 감소합니다.
계산이 까다롭기 때문에 활용도는 조금 떨어진다고 생각합니다. 원리 정도만 이해하고 넘어갑시다.
2-2-2-3. flex-basis
Item의 (공간 배분 전) 기본 너비를 설정합니다.
값이 auto일 경우 width, height 등의 속성으로 Item의 너비를 설정할 수 있습니다.
하지만 단위 값이 주어질 경우 설정할 수 없습니다.
값 | 의미 | 기본값 |
---|---|---|
auto | 가변 Item과 같은 너비 | auto |
단위 | px, em, cm 등 단위로 지정 |
flex 속성에서 설명한 것 같이 단축 속성 내에서 flex-basis를 생략하면 값이 0이 되는 것을 주의합시다.
2-2-3. align-self
교차 축(cross-axis)에서 개별 Item의 정렬 방법을 설정합니다.
align-items는 Container 내 모든 Items의 정렬 방법을 설정합니다.
필요에 의해 일부 Item만 정렬 방법을 변경하려고 할 경우 align-self를 사용할 수 있습니다.
이 속성은 align-items 속성보다 우선합니다.
값 | 의미 | 기본값 |
---|---|---|
auto | Container의 align-items 속성을 상속받음 | auto |
stretch | Container의 교차 축을 채우기 위해 Item을 늘림 | |
flex-start | Item을 각 줄의 시작점(flex-start)으로 정렬 | |
flex-end | Item을 각 줄의 끝점(flex-end)으로 정렬 | |
center | Item을 가운데 정렬 | |
baseline | Item을 문자 기준선에 정렬 |
3.정리
이번 포스팅 에서는 FLEX 에 대해서 알아보았습니다.
이번 포스팅에서 FLEX의 감을 익히셨다면 성공입니다. 이해를 하지 못했다고 해서 낙심하지 마시라는 말씀 드리고 싶네요 Flex 는 그만큼 어려운 주제인것 같습니다. 하지만 한번 익혀두면 그 열매는 매우 크고 달콤 할 것입니다.