StyleSheet/CSS

모던 레이아웃 - 플렉스박스(Flexbox)

jaiyah 2019. 1. 7. 10:46

플렉스박스(Flexbox) 개요

불과 몇 해 전까지만해도 float, position 만으로도 어느 정도의 레이아웃 구현이 가능했습니다. 
하지만 데스크탑 시대를 벗어나 모바일 시대에 접어들면서 보다 유연한 형태의 레이아웃 매커니즘의 필요성이 커져버렸습니다.
그에 따른 차세대 모던 레이아웃에는 플렉스박스(Flexbox), 멀티 컬럼(Multi Columns), 그리드(Grid) 가 있으며,
이번 챕터에서는 Flexbox 레이아웃 모듈을 다뤄봅니다.






CSS Flexible Box Layout Module

일명 flexbox라 불리는 Flexible Box moduleflexbox 인터페이스 내의 아이템 간 공간 배분과 강력한 정렬 기능을 제공하기

위한 1차원적인 레이아웃 모델로 설계되었습니다.


flexbox 를 1차원이라 칭하는 것은, 레이아웃을 다룰 때 한 번에 하나의 차원(행이나 열)만을 다룬다는 뜻입니다.
이는 행과 열을 함께 조절하는 CSS 그리드 레이아웃의 2차원 모델과는 대조됩니다.


정확하게 플렉스박스 레이아웃이란 무엇을 의미하고 어떤 장점이 있을까요?
이 레이아웃을 형성하는 가장 기본적인 모델은 플렉스 컨테이너(flex container)와 관련이 있습니다.
이 컨테이너의 콘텐츠를 플렉스 항목(flex items)이라고 하며, 이 플렉스 항목의 가장 기본적인 기능은 크기를 "유연"하게 조절하는 능력입니다.
즉, 공간에 따라서 가로 또는 세로의 길이를 조절할 수 있으며 가용 공간에 대한 비율을 기반으로 크기를 조절할 수도 있습니다.
플렉스 항목이 자랑하는 또 하나의 인상적인 기능은 시각적인 순서와 방향을 정할 수 있다는 것입니다.
간단히 말해서 플렉스박스 레이아웃 모듈은 우리가 원하는 순서나 방향에 따라 플렉스 항목들이 나타나게 할 수 있고 실제 마크업된 순서와 상관없이 별개로 동작하기 때문에 접근성에 제약을 받지 않는다는 점입니다.
또한 플렉스 박스 모듈은 정렬을 제어하는 능력을 가지고 있습니다.
너비와 간격을 대등하게 하고 또 단의 높이를 동일하게 할 수 있으며 수직 정렬(vertical align)도 간단히 제어할 수 있습니다.


다음은 flexbox 지원 현황입니다.

Can I Use flexbox? Data on support for the flexbox feature across the major browsers from caniuse.com.


구시대의 전유물인 IE, 전 세계적으로 IE 사용률은 저조하지만 국내 사용률은 매우 높은 편입니다.
더이상 개발되지 않는 IE(Edge 제외)를 고려해야 하는 국내 환경을 봤을 땐 flexbox 의 IE 지원율이 미비하기 때문에 선택적 판단을 하여 제작(사용)해야 합니다.
항상 실무에서는 어떠한 기술이든지 프로젝트의 초기 단계에서 고려할 운영체제/브라우저 버전 및 사용할 기술을 정하고 프로젝트를 구성해야 할 필요성이 있습니다.



Flex 컨테이너(부모) 요소 속성

HTML
<div class="flex-container">
	<div class="flex-item">F</div>
	<div class="flex-item">L</div>
	<div class="flex-item">E</div>
	<div class="flex-item">X</div>
	<div class="flex-item">B</div>
	<div class="flex-item">O</div>
	<div class="flex-item">X</div>
</div>


flex 컨테이너 VS flex 아이템

CSS
.flex-container {
    display: flex;

    flex-direction: row; /* 기본값 */
    /* flex-direction: row | row-reverse | column | column-reverse */

    justify-content: flex-start; /* 기본값 */
    /* justify-content: flex-start | center | flex-end | space-between | space-around | space-evenly */
}


display:flex - 플렉스 서식 환경 구성

이 속성을 요소에 적용할 때 이 display 값들은 콘텐츠를 위해 새로운 플렉스 서식 환경(flex formatting context)를 만들게 되고 그 콘텐츠들은 바로 플렉스 항목(flex-item)이 됩니다.

즉, 부모 요소에 display:flex; 를 설정하게 되면 그 부모 요소는 플렉스 컨테이너가 되고 자식 요소는 플렉스 아이템으로 인식하게 됩니다.

기억해야할 점은 flexbox 레이아웃 모듈을 구성할 때는 콘텐츠(플렉스 항목)를 감싸는 부모 요소에 이 속성을 지정해야 한다는 것입니다.

그리고 컨테이너 요소가 플렉스박스가 되면 자식인 모든 플렉스 아이템들은 기본 흐름(flow)이 각각 행(row)을 기준으로 배치하게 됩니다.

앞서 언급했듯이 flexbox 의 콘텐츠(플렉스 항목)는 어떤 방향에든 위치할 수 있으며, 동적으로 변경가능한 순서를 지정할 수도 있고, 가용한 공간 내에서 크기와 위치를 자동으로 조정하기도 합니다.


flex-direction - 방향, 흐름, 시각적인 순서처리

플렉스 항목들은 행을 기준으로 배치되며, flex-direction 속성을 통해 변경이 가능합니다.

flex-direction 속성은 요소의 흐름 방향을 제어하는 것으로, 즉 플렉스 항목들이 오른쪽, 왼쪽, 아래쪽, 위쪽 방향 중 어느 쪽으로 정렬(배열)되어야 하는지를 제어하게 됩니다. flex-direction 속성의 기본값은 row 이고, 이는 서양식 쓰기 방식(왼쪽에서 오른쪽, 위에서 아래쪽 쓰기)을 기본으로 하여 플렉스 항목들이 나열되도록 합니다.


기본값이 flex-direction: row; 이므로 따로 정의해 주지 않아도 행을 기준으로 배치되며, 그 외의 속성값은 다음과 같습니다.

  • row : 기본값이고, 왼쪽에서 오른쪽으로 나열한다. (→)
  • row-reverse : 오른쪽에서 왼쪽으로 나열한다. (←), 즉, 뒤집기(reverse)를 합니다.
  • column : 항목들을 수직으로 위쪽에서 아래쪽을 향해 나열한다. (↓)
  • column-reverse : 항목들을 수직으로 아래쪽에서 위쪽으로 나열한다. (↑)

flex-direction DEMO VIEW



flex-direction은 플렉스 항목들의 흐름 방향을 전체적으로 제어하기 때문에 플렉스 항목이 아닌 플렉스 컨테이너에 지정해야 합니다.

그리고 float 레이아웃을 사용할 때는 변칙적인 clear 속성을 이용해 부모가 자식을 감싸주도록 하는 방법을 사용했지만 플렉스 박스는 컨테이너 요소에 display: flex 만 주게 되면 마치 모든 아이템에 float 를 정의해 준 것처럼 배치가 되면서 굳이 불필요하게 clearfix 라는 방식을 사용하지 않아도 됩니다.


flex-wrap

flex-wrap 은 플렉스 항목들이 열을 바꾸는 방법을 제어하는 속성으로, 즉 flex item 을 감쌀(wrap) 것인지 감싸지 않을 것인지를 지정합니다.
이 값이 적용되면 항목들이 여러 개의 열로 나뉘지 않고 여러 항목들이 너비를 조정해서 하나의 열 안아 모두 끼워 넣어지게 됩니다.

플렉스 아이템들 전체 폭의 합보다 부모 너비가 작은 경우(CSS 에선 보통 overflow 되었다고 함)에 유용하게 사용할 수 있습니다.

기본값이 nowrap 이기 때문에 플렉스컨테이너가 플렉스 아이템들의 너버합보다 작은 경우에 넘쳐 흐르게 됩니다.
즉, 항목의 수가 늘어나도 한 줄로 늘어서게 됩니다. (white-space: nowrap 과 유사)



flex-wrap 속성값은 다음과 같습니다.

  • nowrap : 기본값으로 플렉스 항목들이 wrap 되지 않도록 지정합니다.
  • wrap : 플렉스 항목들이 컨테이너 안에서 여러 줄로 열 바꿈을 할 수 있게 허용합니다.
  • wrap-reverse : 주축은 그대로 유지하면서 교차축을 기준으로 뒤집히게 배치 됩니다.
  • initial : 디폴트 값으로 이 속성을 설정합니다.
  • inherit : 부모 요소로부터 값을 상속 받습니다.

flex-wrap DEMO VIEW



flex-flow - 속기형

이 속성은 앞서 학습했던 flex-directionflex-wrap 값을 명시하는 단축 속성입니다.

flex-flow 는 두 개의 인자(매개변수)를 순서에 상관없이 지정할 수 있고 둘 중의 하나를 생략하는 것도 가능합니다.

일반적으로 다음과 같은 순서를 권장합니다.

CSS
.flex-container {
    display: flex;
    flex-flow: direction wrap;
}

flex-flow DEMO VIEW



flex 컨테이너 플로우 축(axis)


플렉스 박스를 자세히 이해하기 위해서는 축(axis)에 대해 학습할 필요가 있습니다.

이 축(axis)은 정렬하기 위해 필요한 것으로 메인(주) 축과 교차축이 있습니다.

기본적으로display:flexdirection 값은 행(row)입니다. 그래서 행을 기준점으로 주축이 설정이 됩니다.
즉, main axis 가 주축이 되는 것입니다.
반면에 교차축(cross axis)는 주축을 가로지르는 축을 말합니다.

그리고 메인축(main axis)에는 시작(main axis start), 중간(center), 끝점(main axis end)이 있는데 이 지점들의 이름을 flex-start, center, flex-end 라고 말합니다.

또한 교차축도 시작점, 중간, 그리고 끝점이 있습니다. 교차축에서도 flex-start, center, flex-end 라고 칭합니다.

다시 말해, 주축이든 교차축이든 시작, 중간, 끝점이 있습니다.
하지만 flex-direction 을 column 으로 변경했을 때 이 축간에 차이점이 발생합니다.

column 으로 변경되면 row 일때 교차축이 주축이 되고 반대로 주축이 교차축으로 바뀌게 됩니다.
그렇기 때문에 flex-direction 속성은 보다 중요합니다.

이렇게 flex 의 등장으로 인해서 예전(float, position)보다 flex-direction 과 배치(start, center, end)를 이용하면 좀 더 유연한 배치가 가능해졌으며, 이를 모던 레이아웃이라고 합니다.



justify-content - 콘텐츠 정렬

justify-content 의미에서도 알 수 있듯이 콘텐츠를 정렬하는 것인데 이때 중요한 점은 주축에 대한 정렬을 의미한다는 점입니다.

즉, 주축(main axis)에 대한 정렬이므로 교차축에 대한 정렬값도 따로 존재한다는 뜻입니다.

다시 말해, 기본 flex-direction의 값은 row 라는 가정하에 동작하며, 이것은 플렉스 항목의 진행이 왼쪽에서 오른쪽(→), 그리고 위에서 아래(↓)로 나열되는 것을 의미합니다.

교차축에 대한 정렬은 뒤따라 알아보도록 하고 먼저 justify-content 속성값들에 대해 알아보겠습니다.

  • flex-start : 기본값으로 플렉스 항목들을 플렉스 컨테이너의 시작 부분(왼쪽)부터 정렬합니다.
  • flex-end : 플렉스 항목들을 컨테이너의 끝 부분(오른쪽)부터 시작점으로 정렬합니다.
  • center : 플렉스 항목들을 컨테이너의 중앙에 정렬합니다.
  • space-between : 플렉스 항목 중에 첫 번째 항목은 왼쪽 끝, 마지막 항목은 오른쪽 끝에 정렬하고 다른 항목들은 그 사이에 남는 공간을 일정한 간격으로 분배하여 배열합니다. 다시 말해, a와 b 사이의 공간, b와 c 사이의 공간으로 분배합니다.
  • space-around : space-between 과 동일하게 적용되지만 첫 번째와 마지막 항목이 각가 왼쪽과 오른쪽의 끝으로 정렬하지 않고, 정렬된 항목들 주위로 둘러싸여(around) 골고루 분배합니다.
  • space-evenly : 이 속성을 사용하면 완전히 균등한 공간으로 배분할 수 있습니다.
  • initial : 이 속성의 기본값을 따릅니다.
  • inherit : 부모 요소로부터 값을 상속 받습니다.


justify-cotent DEMO VIEW



Flexbox Layout Module Demo View

다음의 예제의 좌측은 컨테이너의 부모 요소에 적용할 수 있는 속성이며, 오른쪽은 자식 요소에 설정할 수 있는 속성으로 구성되어 있는 예제입니다.

DEMO VIEW(참고 :https://codepen.io/jaehee/full/zyZyWZ)



align-content

justify-content가 메인(주)축을 기준으로 배치한다면 align-content는 교차축(cross axis)에 대한 정렬 배치를 하게 됩니다.

플렉스 아이템들에 대한 개별 하나하나의 정렬이 아닌 플렉스 아이템들을 한덩어리(그룹)로 정렬 배치하는 속성입니다.

CSS
.flex-container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 200px;
    height: 400px;

    /* 교차축에 대한 정렬 */
    align-content: flex-start;
    /* align-content: flex-start | center | flex-end | space-between | space-around | space-evenly | stretch */
}
.flex-item {
    flex: 0 0 50px;
}

  • flex-start : 교차축에 대한 정렬로 컨테이너의 맨 위에서부터 덩어리로 플렉스 아이템들을 배치시키게 됩니다. 여유 공간은 이 열들의 아래 쪽에 표시됩니다.
  • center : 교차축에 대해 수직 방향을 기준으로 중앙 정렬된 상태가 됩니다.
  • flex-end : 교차축에 대해 컨테이너의 바닥으로 정렬합니다. 여유 공간은 이 열들의 위쪽으로 표시됩니다.
  • space-between, space-around, space-evenly : justify-content 와 동작이 같으나 교차축에 대한 정렬 배치를 합니다.
  • stretch : 기본값으로, 컨테이너의 높이와 동일하도로 항목들의 높이를 조정합니다.(단, 플렉스 아이템 높이가 정의되어 있지 않은 경우에)

align-content DEMO VIEW



가운데 배치 설정


align-items

align-items 속성은 플렉스 항목의 교차축에 대한 정렬을 각각의 항목들과 연관시켜서 제어, 배치할 수 있습니다.

align-items 에 대한 속성값은 다음과 같습니다.

  • stretch : 기본값이고, 모든 플렉스 항목들이 서로 일치(높이값 동일)하도록 조정합니다.
  • flex-start : 플렉스 항목들을 플렉스 컨테이너의 시작 부분(왼쪽)에 위치시키지만 각 항목의 높이는 각 항목의 콘텐츠 양에 따라 결정됩니다.
  • flex-end : flex-start 와 동일한 규칙이지만 플렉스 항목들을 컨테이너의 아래쪽으로 배치합니다.
  • center : 각 항목의 위 아래 잔여 공간을 동일하게 분배하기 때문에 각 항목이 수직을 기준으로 중앙에 정렬합니다.
  • baseline : 모든 플렉스 항목을 콘텐츠에 지정된 기준선을 중심으로 정렬합니다. 기준선은 각 항목마다 다를 수 있습니다.

align-items DEMO VIEW


justify-content 는 주축에 대한 정렬 배치를 나타내는데 flex-direction 의 방향이 column 으로 주축의 방향이 바뀌게 된다면 justify-content, align-content 에 대한 방향도 바뀌게 됨을 기억해야 합니다.

다시 말해, flex-direction: column; 이 된다면 justify-content: flex-start; 는 위에서 아래로의 주축에 대한 정렬 배치를 하게 됩니다.





flex 아이템(자식) 요소 속성

위에서 알아본 플렉스 속성은 플렉스 컨테이너에 정의하여 사용되는 속성들이었습니다.

이제부터 알아 볼 속성들은 플렉스 아이템들에 대한 레이아웃 속성들로서 플렉스 항목(flex item)에 정의하여 사용하는 속성들임을 상기하며 학습해 봅니다.


flex-***(단일 속성)과 flex(속기형)

플렉스 항목(flex item)들 각각의 너비를 지정할 수 있고 각 항목 사이에 배분되는 여유 공간을 지정해 줄 수 있는데, 이 속성들에 대해 알아봅니다.

CSS
.flex-container {
    display: flex;
}
.flex-item {
    flex-grow: 1;
    flex-shrink: 0;
    flex-basis: 150px;
    /* 속기형(순서 중요)*/
    flex: grow shrink basis;
}

flex-basis

CSS 에서 요소의 너비는 width 로 정의하여 사용했으나 플렉스를 사용하면 플렉스 아이템(flex item)의 너비는 flex-basis를 사용하여 너비를 지정할 수 있습니다.

즉, flex-basis 속성은 너비 값을 정의하고 플렉스 항목의 초기 크기를 설정합니다. 이후 남는 공간은 증가/감소(glow/shrink) 인자들을 근거로 분배됩니다.
또한 이 속성은 플렉스 항목의 기본값을 지정하는 것이고 기본값은 auto 입니다.

flex-basis DEMO VIEW



flex-grow

flex-grow는 플렉스 아이템의 너비를 늘어나도록 정의해 줄 수 있는 속성입니다.

이 속성은 양수, 정수값을 사용하고 이 값은 남는 공간 중 얼마를 지정된 플렉스 항목에 분배해야 하는지 그 정도를 제어합니다.

다시 말해, flex-grow: 1; 1 이면 자동으로 플렉스 아이템들의 너비가 플렉스 컨테이너의 너비를 기준으로 알맞게 균등 배분하여 성장(확장)하여 늘어나게 됩니다.

flex-grow: 0;기본값으로 플렉스 컨테이너의 너비에 맞춰서 늘어나지 않는다는 의미입니다.


여기서 주의할 점은 flex-grow: 0; 일 경우에 플렉스 컨테이너 너비를 기준으로 늘어나지 않기 때문에 각각의 아이템들의 너비 지정이 가능합니다. 하지만 flex-grow: 1; 과 같이 1이상의 값을 가지게 되면 플렉스 컨테이너 너비를 기준으로 확장해라란 의미이기 때문에 아무리 모든 플렉스 아이템이든 제각각의 아이템들이든 간에 width:150px; 또는 flex-basis:150px; 를 정의해 주면 이 너비들은 무시되어 의도한 대로 너비가 표현되지 않음을 기억해야 합니다.

flex-grow DEMO VIEW


flex-shrink

flex-shrinkflex-grow와는 반대로 플렉스 아이템의 너비를 줄어(축소)들도록 정의해 줄 수 있는 속성입니다.

flex-shrinkflex-grow 와 유사하게 동작하는데, flex-shrink: 1; 을 사용자가 정의했고 플렉스 아이템 5개가 있으며 각 아이템에 정의된 너비가 100픽셀이며 플렉스 컨테이너의 너비가 600픽셀을 정의했다고 가정해 봅시다.

이 경우에 플렉스 컨테이너의 너비의 합은 플렉스 아이템들의 합보다 크기 때문에 각 플렉스 아이템들에게 지정된 100픽셀의 너비를 가지게 됩니다.
하지만 여기서 플렉스 컨테이너가 플렉스 아이템들의 합보다 작아졌을 때 각 아이템에 지정된 너비는 무시되면서 플렉스 컨테이너 너비를 기준으로 각 플렉스 아이템들이 줄어들게 됩니다.

즉, 플렉스 아이템 너비의 합이 플렉스 컨테이너보다 클 경우에 flex-shrink: 1;이 정의되어 있다면 플렉스 컨테이너 너비를 기준으로 플렉스 아이템들이 균등 분할하게 됩니다.

flex-shrink DEMO VIEW


flex-direction 에 따른 너비, 높이값

flex-grow, flex-shrink 값이 1인 경우, flex-direction 값에 따라 기준이 달라집니다.

플렉스 주축 방향이 row(기본 값)이라면 width 이고, column 일 경우는 height 입니다.

  • flex-direction: row; ⟹ width
  • flex-direction: column; ⟹ height

Flexbox 레이아웃 기술을 사용하는 이유는 유연한 박스 크기 변경 때문입니다.
기존의 width, min-width, max-width, height, min-height, max-height 속성과 float, position 속성 조합 만으로는 한계가 있어 이를 해결하기 위한 방안으로 등장한 기술입니다.


flex:0 1 auto; : flex-grow 속성 기본 값이 0, flex-shrink 속성 기본 값이 1, flex-basis 속성 기본 값이 auto 입니다.

즉, 기본적으로 Flex 아이템 요소는 컨테이너 요소보다 크기가 커질 경우 축소(shrink) 되며,
컨테이너 요소 보다 크기가 작을 경우 확장(grow) 되지는 않습니다.


아래 코드처럼 속성을 설정하면 확장, 축소, auto 가 모두 설정된 것입니다.

.flex-item {
    flex: 1;  /* 1 1 auto */
}

Flexbox 레이아웃을 사용할 때, 이렇게 사용하는 경우는 빈번합니다.

참고로 flex-basis 값이 설정 되었다면 width 또는 height 속성 보다 우선 적용됩니다.




flex 속기형

앞서 알아본 flex-grow, flex-shrink, flex-basis 속성들을 축약 속성인 속기형으로 지정할 수 있습니다.

flex 속성을 사용하여 확장, 감소, 초기 기본 너비를 한 번에 정의할 수 있으며, 중요한 것은 앞서 작성한 순서를 그대로 지켜야 합니다.

그리고 flex 의 기본값은 flex: 0 1 auto; 입니다.

CSS
.flex-item {
    /* flex-grow 는 필수값 나머지는 옵션값 */
    flex: flex-grow [flex-shrink] [flex-basis];
}

flex 속성,값은 다음과 같습니다.

  • flex-grow : 플렉스 항목들이 차지할 너비들에 대한 증가형 숫자를 지정합니다. 기본값은 0 입니다.
  • flex-shrink : 플렉스 항목들이 차지할 너비들에 대한 감소형 숫자를 지정합니다. 기본값은 1 입니다.
  • flex-basis : item 의 길이를 지정합니다.
  • auto : 1 1 auto 와 같습니다.
  • initial : 0 1 auto 와 같습니다.
  • none : 0 0 auto 와 같습니다.

flex 의 이점

기존에 float 를 사용하면 컨테이너 요소의 너비에 따라 자식 요소의 너비를 항상 계산해줘야 했으며, 수정사항이 생겨 유지보수의 문제가 생기면 자식 요소의 너비를 다시 계산해 주어 다시 재정의 해줘야하는 번거로움이 있습니다.
하지만 플렉스 박스는 자동으로 계산하여 배치해주기 때문에 유지보수 측면에도 큰 이점을 가지고 있습니다.



grow, shrink 숫자가 증가, 감소에 따라 어떻게 계산될까?

플렉스 컨테이너 요소에 설정된 주축의 방향은 row 입니다.
즉, 왼쪽 ⇒ 오른쪽 방향입니다. 아이템의 배치는 수평으로 나란히 배치가 됩니다.
아이템에 설정된 flex-basis 값은 너비(width)를 말하게 됩니다.
만약 column 이 설정되면 basis 는 높이(height)를 말하게 됩니다.

.flex-container {
    display: flex;
    flex-flow: row wrap;
}
.flex-item {
    flex: 1 0 50px;
}

플렉스 아이템 요소에 설정된 위의 코드를 보면 다음과 같습니다.
아이템의 shrink 값이 0 이므로 주축 방향으로 basis 값인 50px 보다 축소되지 않습니다.
즉, 최소 50px의 너비(width) 설정입니다. 반면 grow 값은 1 이므로 50px 이상 확장될 수 있습니다.

현재 부모 컨테이너 요소에 별도로 width 너비 값이 설정되지 않았다면 브라우저 창 크기(너비)에 따라 유연한 값을 가집니다. 즉, 창 너비가 고정되지 않은 것입니다.

이이템이 7개 있다고 가정해 봅니다.
아이템의 너비가 50px 이상 확장 되려면 부모의 너비가 아이템 7개의 너비 합(350px) 보다 커야 합니다.
그래야 아이템이 확장될 공간이 생길 것이기 때문입니다.
grow 값은 확장될 공간이 없으면 확장될 수 없습니다.

만약 부모 컨테이너의 너비 값이 500px이 된다고 하면 남은 공간은 500 - 350 = 150px 이 됩니다.
그럼 각 아이템은 150 / 7 = 21.4285px 만큼 공간을 나눠 가지게 됩니다.
즉, 각 아이템은 50 + 21.4285 = 71.4285px 값의 너비로 확장(grow) 됩니다.


다른 예시를 들어보도록 하겠습니다.

아이템 중 3번째 자식 요소인 아이템(3)에 설정된 코드는 아래와 같습니다.

.flex-item:nth-child(3) {
    flex: 2 0 20px;
}

여기서 포인트는 grow 값이 1이 아닌, 2로 설정된 부분입니다.

위 값은 부모 컨테이너 요소의 남은 너비 공간을 나눠 확장할 때 다른 박스보다 2만큼 더 큰 비율로 나눠진 값으로 확장하라는 것입니다.

쉽게 말해 각 아이템 박스가 나눠 가질 공간의 비율은 다음과 같습니다.

1 : 1 : 2 : 1 : 1 : 1 : 1

예를 들어 남은 공간이 70px 이라고 한다면 아이템(3) 요소의 너비는 2/8 = 25% 만큼 확장(17.5px) 하고
다른 아이템들은 1/8 = 12.5% 만큼(8.75px) 너비 값을 확장하게 됩니다.

((70 * 1/8) * 6) + ((70 * 2/8) * 1) = 70


만약 부모 컨테이너의 너비 값이 500px이 된다고 하면 남은 공간은 500 - 350 = 150px 이 됩니다.

아이템(3)은 남은 공간 중 25% 를 가지니까 150 * 2/8 = 37.5px 만큼 확장 되고,
다른 아이템은 남은 공간 중 12.5% 를 나눠 가질테니 150 * 1/8 = 18.75px 만큼 공간을 나눠 확장됩니다.


shrink 는 축소이니, grow 설정의 반대로 생각하시면 됩니다.

부모 컨테이너 너비 값이 아이템 너비의 합보다 작을 경우, 축소가 반영됩니다.

이번에는 부모 컨테이너 너비 - 아이템 너비의 합 = 축소해야 할 공간 이 될 것이고,
이 또한 shrink 설정 값의 비율에 따라 축소해야 할 공간이 브라우저에 의해 계산 처리 반영될 겁니다.

flex-grow - CSS | MDN




아이템 순서 설정

앞선 내용에서 flex-direction, flex-wrap 그리고 이 두 개의 단축 속성을 지정할 수 있는 flex-flow 들은 플렉스 항목의 순서와 방향을 효과적으로 제어할 수 있게 해줍니다.

그런데 시각적인 순서에 관해서는 이보다 더 제어력이 뛰어난 order 라는 속성이 있습니다.

order

order 속성은 정수 기반의 값을 수용하기 때문에 z-index 개념과 유사한 방식으로 작용합니다.

다만 레이어 층으로 구성하지 않고 요소의 흐름상 플렉스 항목이 어디에 나타나야 하는지 그 위치를 결정합니다.

모든 플렉스 항목은 order 값은 0 을 기본값으로 갖게 되고 플렉스 항목들이 동일한 order 값을 공유할 경우 소스에 적힌 순서(마크업 순서)대로 나열(배열)됩니다.

이러한 작업은 float 를 통해서 매우 힘들게 구현했지만 order 에 적용된 숫자값만으로도 매우 유연하게 순서를 배치할 수 있습니다.



CSS
.flex-container {
    height:200px;
    flex-flow: row wrap;
}
.flex-item {
    display:flex;
    flex: 1 0 50px;
    justify-content:center;
    align-items:center;
}
.flex-item:nth-child(1) { order:2; }
.flex-item:nth-child(2) { order:0; }
.flex-item:nth-child(3) { order:-2; }
.flex-item:nth-child(4) { order:1; }
.flex-item:nth-child(5) { order:3; }
.flex-item:nth-child(6) { order:0; }
.flex-item:nth-child(7) { order:-1; }

order DEMO VIEW


order 를 사용할 때 좋은 점은 이것이 실제 콘텐츠와 별개로 동작한다는 점 입니다.

즉, 마크업을 논리적으로 구성하고 디자인 측면에서 마크업 순서와 상관없이 콘텐츠 구조를 자유롭게 배치시킬 수 있기 때문에 웹 접근성에 위배되지 않도록 구성할 수 있습니다.(스크린 리더나 그 외의 보완기술을 사용하는 사람들에게 웹 접근의 어려움을 최소화시킵니다.)



align-self

마지막으로 플렉스 아이템에 설정 가능한 속성으로 align-self 가 있습니다.

앞서 학습한 내용을 상기해 보면 플렉스 컨테이너인 부모에서 설정 가능한 속성으로 align-content 속성과 align-items 속성을 살펴보았습니다.

align-content 는 아이템 그룹을 제어할 때 사용하고 align-items는 개별 아이템을 제어할 때 사용할 수 있었습니다.

align-self 는 부모에 설정해 주는 align-items와 유사합니다.

align-items는 자식들에게 일괄적으로 제어해주는 설정을 해줬다면 align-self는 자식 자신한테만 설정해주는 것입니다.

즉, 자신한테만 독자적으로 설정할 때 제어하는 속성으로 auto 가 기본값입니다.

여기서 또 하나 중요한 점은 align-contentalign-items 속성과 마찬가지로 교차축에 대한 정렬을 다루는 속성입니다.

CSS
.flex-container {
    height:200px;
    flex-flow: row wrap;
}
.flex-item {
    display:flex;
    flex: 1 0 50px;
    justify-content:center;
    align-items:center;
}
.flex-item:nth-child(1) {}
.flex-item:nth-child(2) {}
.flex-item:nth-child(3) {
    flex:1 0 20px;
    height: 100px;
    align-self: stretch;
}
.flex-item:nth-child(4) {}
.flex-item:nth-child(5) {}
.flex-item:nth-child(6) {}
.flex-item:nth-child(7) {}

align-self 속성값은 다음과 같습니다.

  • stretch : 기본값으로 모든 플렉스 항목들이 서로 일치(높이값 동일)하도록 조정합니다.
  • flex-start : 플렉스 항목들을 플렉스 컨테이너의 시작 부분(왼쪽)에 위치시키지만 각 항목의 높이는 각 항목의 콘텐츠 양에 따라 결정됩니다.
  • flex-end : flex-start와 동일한 규칙이지만 플렉스 항목들을 컨테이너의 아래쪽으로 배치합니다.
  • center : 각 항목의 위 아래 잔여 공간을 동일하게 분배하기 때문에 각 항목이 수직을 기준으로 중앙에 정렬합니다.
  • baseline : 모든 플렉스 항목을 콘텐츠에 지정된 기준선을 중심으로 정렬합니다. 기준선은 각 항목마다 다를 수 있습니다.

align-self DEMO VIEW



flex 모던 레이아웃 모듈을 마치며

플렉스박스는 새롭고 흥미진진하며 혁신적입니다. 무엇보다도 반응형 웹에 관한 움직임에 대처하고 웹 페이지를 구현하는 포괄적인 도구로써 자리매김하기 위해서는 현재 CSS가 반드시 갖춰야하는 모듈일 것입니다.

그리고 현재 IE 를 제외한 여러 브라우저들이 플렉스박스를 지원하고 접두어(vendor-prefix)를 제거하고 있는 이 시점에 더 늦기 전에 이 IT업계의 종사자들이 이 모던 레이아웃 모듈에 대한 초기 공포와 경계심을 떨쳐버리고 한 발짝 더 다가가야 할 시점입니다.

이제는 더이상 미루어야 할 차세대 기술이 아님을 인지하고 자신의 프로젝트에 다양하게 적용해 볼 수 있는 계기를 되길 바랍니다.





Jaehee's WebClub