flexbox의 기본 개념

일명 flexbox라 불리는 Flexible Box module은 flexbox 인터페이스 내의 아이템 간 공간 배분과 강력한 정렬 기능을 제공하기 위한 1차원 레이아웃 모델 로 설계되었습니다. 이 글에서는 flexbox의 주요 기능에 대한 개요를 다룹니다. 더 자세한 내용은 가이드의 다른 글에서 탐구하게 될 것입니다.

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

flexbox의 두 개의 축

flexbox를 다루려면 주축과 교차축이라는 두 개의 축에 대한 정의를 알아야 합니다. 주축은 flex-direction 속성을 사용하여 지정하며 교차축은 이에 수직인 축으로 결정됩니다. flexbox의 동작은 결국 이 두 개의 축에 대한 문제로 환원되기 때문에 이들이 어떻게 동작하는지 처음부터 이해하는 것이 중요합니다.

주축

주축은 flex-direction에 의해 정의되며 4개의 값을 가질 수 있습니다:

  • row
  • row-reverse
  • column
  • column-reverse

row 혹은 row-reverse를 선택하면 주축은 인라인 방향으로 행을 따릅니다.

If flex-direction is set to row the main axis runs along the row in the inline direction.

column 혹은 column-reverse 을 선택하면 주축은 페이지 상단에서 하단으로 블록 방향을 따릅니다.

If flex-direction is set to column the main axis runs in the block direction.

교차축

교차축은 주축에 수직하므로, 만약 flex-direction(주축)이 rowrow-reverse 라면 교차축은 열 방향을 따릅니다.

If flex-direction is set to row then the cross axis runs in the block direction.

주축이 column 혹은 column-reverse 라면 교차축은 행 방향을 따릅니다.

If flex-direction is set to column then the cross axis runs in the inline direction.

flex 요소를 정렬하고 끝을 맞추(justify)려면 어느 축이 어느 방향인지 이해하는 것이 중요합니다; flexbox는 주축, 교차축을 따라 항목을 정렬하고 끝을 맞추는 각종 속성들을 적용하는 방식으로 동작합니다.

시작선과 끝선

flexbox가 쓰기 방법(writing mode)을 가정하지 않는다는 것은 상당히 중요합니다. 과거의 CSS는 왼쪽에서 오른쪽으로 향하는 가로 방향의 쓰기 방법에 치우쳐 있었습니다. 하지만 현대의 레이아웃은 다양한 쓰기 방법을 포괄해야 하므로, 더이상 텍스트가 문서의 왼쪽 상단에서 시작해서 오른쪽으로 향한다고 가정하지 않습니다. 새 라인이 항상 아래에 쌓인다고 가정하지도 않습니다.

다른 글에서 flexbox와 쓰기 방법 명세(writing mode spec.)가 어떤 관련이 있는지 알아볼 수 있습니다. 그 전에, 이 글에서 flex 요소의 정렬 방향에 "왼쪽, 오른쪽, 위, 아래"를 사용하지 않는 이유를 알 수 있었으면 합니다.

flex-directionrow고 영어 문장을 문서에 쓰고 있다면, 주축의 시작선은 왼쪽 끝, 끝선은 오른쪽 끝이 될 것입니다.

Working in English the start edge is on the left.

아랍어 문장을 쓰고 있다면, 주축의 시작선은 오른쪽 끝, 끝 선은 왼쪽 끝이 될 것입니다.

The start edge in a RTL language is on the right.

영어와 아랍어는 모두 가로 쓰기를 채택하고 있으므로 두 예시에서 교차축의 시작선은 flex 컨테이너의 위 끝이며 끝선은 아래 끝입니다.

조금만 지나면 왼쪽-오른쪽으로 생각하는 것보다 시작선-끝선으로 생각하는 것이 금새 자연스러워질 것입니다. 동일한 패턴을 따르는 CSS 그리드 레이아웃 같은 방법을 다룰 때도 쉽게 적응할 수 있을 것입니다.

flex 컨테이너

문서의 영역 중에서 flexbox가 놓여있는 영역을 flex 컨테이너라고 부릅니다. flex 컨테이너를 생성하려면 영역 내의 컨테이너 요소의 display 값을 flex 혹은 inline-flex로 지정합니다. 이 값이 지정된 컨테이너의 일차 자식(direct children) 요소가 flex 항목이 됩니다. display 속성만 지정하여 flex 컨테이너를 생성하면 다른 flex 관련 속성들은 아래처럼 기본 값이 지정됩니다.

  • 항목은 행으로 나열됩니다. (flex-direction 속성의 기본값은 row입니다).
  • 항목은 주축의 시작 선에서 시작합니다.
  • 항목은 주 차원 위에서 늘어나지는 않지만 줄어들 수 있습니다.
  • 항목은 교차축의 크기를 채우기 위해 늘어납니다.
  • flex-basis 속성은 auto로 지정됩니다.
  • flex-wrap 속성은 nowrap으로 지정됩니다.

이렇게되면 flex 항목들은 각 항목 별 내부 요소의 크기로 주축을 따라 정렬됩니다. 컨테이너의 크기보다 더 많은 항목이 있을 경우 행을 바꾸지 않고 주축 방향으로 흘러 넘치게 됩니다. 어떤 항목이 다른 항목보다 높이 값이 크다면 나머지 모든 항목들은 그에 맞게 교차축을 따라 늘어나게 됩니다.

다음의 라이브 예시를 통해 어떻게 보여지는지 확인할 수 있습니다. flexbox의 초기 동작을 시험해보려면 항목을 추가하거나 수정해보시기 바랍니다.

flex-direction 지정

flex 컨테이너flex-direction 속성을 지정하면 flex 항목이 나열되는 방향을 변경할 수 있습니다. flex-direction: row-reverse 라고 지정하면 행으로 나열되는 것은 그대로지만 시작 선과 끝 선이 서로 바뀌게 됩니다.

flex-directioncolumn으로 지정하면 주축이 변경되고 항목들은 열로 나열됩니다. column-reverse로 지정하면 그에 더해 시작 선과 끝 선이 서로 바뀌게 됩니다.

다음의 라이브 예시는 flex-directionrow-reverse로 지정되어 있습니다. row, column, column-reverse와 같은 값을 지정해서 어떻게 되는지 확인해보시기 바랍니다.

flex-wrap을 이용한 복수 행 flex 컨테이너 지정

flexbox는 1차원 모델이지만 flex 항목이 여러 행에 나열되도록 할 수 있습니다. 그 경우 각 행이 새로운 flex 컨테이너라고 생각해야 합니다. 공간 배분은 해당 행에서만 이루어지며 다른 행은 영향을 받지 않습니다.

항목이 여러 행에 나열되도록 하려면 flex-wrap 속성의 값을 wrap으로 지정합니다. 그러면 항목이 하나의 행에 들어가지 않을 정도로 클 경우 다른 행에 배치됩니다. 아래의 라이브 예시에 있는 flex 항목은 폭이 지정되어 있으며 항목들의 폭의 합은 flex 컨테이너에 들어가기에는 너무 넓습니다. flex-wrap속성이 wrap으로 지정되어 있으므로 항목은 여러 행에 나열됩니다. 초깃값과 동일한 nowrap을 지정하고 flex항목에 대한 확대/축소 방식을 별도로 지정하지 않으면 flex 항목들은 컨테이너의 폭에 맞게 줄어듭니다. nowrap을 지정하면 항목이 전혀 줄어들 수 없거나 충분히 줄어들 수 없을 때 흘러넘치게 됩니다.

Mastering Wrapping of Flex Items 가이드에서 더 자세한 내용을 확인할 수 있습니다.

축약형 속성 flex-flow

flex-direction 속성과 flex-wrap 속성을 flex-flow라는 축약 속성으로 합칠 수 있습니다. 첫 번째 값은 flex-direction이고 두 번째 값은 flex-wrap입니다.

다음의 라이브 예시에서 첫 번째 값을 flex-direction에 지정 가능한 값들(row, row-reverse, column or column-reverse)로 바꿔보시기 바랍니다. 두 번째 값도 wrap이나 nowrap으로 바꿔보시기 바랍니다.

flex 항목에 지정 가능한 속성들

flex 항목에 적용할 수 있는 속성은 다음과 같습니다.

이 글에서는 위의 속성들에 대해 간략하게 살펴보겠습니다. 자세한 내용은 Controlling Ratios of Flex Items on the Main Axis에서 다룹니다.

500 픽셀의 크기를 갖는 flex 컨테이너 내에 100 픽셀 크기의 자식 세 개가 존재할 때, 사용가능한 공간 200 픽셀이 남게 됩니다. 기본적으로 flexbox는 이 공간을 마지막 자식 요소 다음에 빈공간으로 남겨둡니다.

This flex container has available space after laying out the items.

위의 세 가지 속성을 변경한다는 것은 flex 항목에게 사용가능한 공간을 분배하는 방식을 변경하는 것입니다. 사용가능한 공간 개념은 flex 항목을 정렬할 때 특히 중요합니다.

flex-basis 속성

flex-basis 속성은 항목의 크기를 결정합니다. 이 속성의 기본값은 auto이며, 이 경우 브라우저는 항목이 크기를 갖는지 확인합니다. 위의 사진 예시의 경우 항목의 크기가 100 픽셀이므로 flex-basis의 값으로 100 픽셀이 사용됩니다.

flex 항목에 크기가 지정되어 있지 않으면, flex 항목의 내용물 크기가 flex-basis 값으로 사용됩니다. 따라서 flex 컨테이너에서 display: flex 속성만을 지정하면 flex항목들이 각 내용물 크기만큼 공간을 차지하게 됩니다.

flex-grow 속성

flex-grow값을 양수로 지정하면 flex 항목별로 주축 방향 크기가 flex-basis 값 이상으로 늘어날 수 있게 됩니다. 위의 사진 예시에서 모든 항목의 flex-grow 값을 1로 지정하면 사용가능한 공간은 각 항목에게 동일하게 분배되며, 각 항목은 주축을 따라 분배받은 값만큼 사이즈를 늘려 공간을 차지합니다.

첫 항목의 flex-grow 값을 2로 지정하고 나머지 두 개의 항목을 1로 지정한다면 각 항목에 지정된 flex-grow 값의 비율에 따라 남은 공간이 분배됩니다. 각 항목의 flex-grow 비율이 2:1:1 이므로 첫 항목에게 100 픽셀, 두 번째와 세 번째 항목에게 50 픽셀씩 분배됩니다.

flex-shrink 속성

flex-grow 속성이 주축에서 남는 공간을 항목들에게 분배하는 방법을 결정한다면 flex-shrink 속성은 주축의 공간이 부족할때 각 항목의 사이즈를 줄이는 방법을 정의합니다. 만약 flex 컨테이너flex 항목을 모두 포함할 만큼 넉넉한 공간을 갖고 있지 않고 flex-shrink 값이 양수이면 flex 항목은 flex-basis에 지정된 크기보다 작아집니다. 또한, flex-grow 속성과 마찬가지로 더 큰 flex-shrink 값을 갖는 항목의 사이즈가 더 빨리 줄어듭니다.

항목의 최소 크기는 실제 축소량을 계산할 때 고려되기 때문에 flex-shrink 속성이 flex-grow 속성에 비해 덜 일관된 모습을 보여줄지도 모릅니다. flex-shrink 속성이 항목의 사이즈를 결정하는 알고리즘에 관해서는 Controlling Ratios of Flex Items on the Main Axis에서 자세히 살펴히보겠습니다.

참고: flex-growflex-shrink의 값이 비율임을 유의하세요. flex 항목의 flex 속성을 모두 1 1 200px 로 지정하고 한 항목만 크기가 늘어나는 비율을 타 항목의 두배로 하고 싶으면 해당 flex 항목의 flex 속성을 2 1 200px로 지정하면 되지만, flex 속성 값을 모두 10 1 200px로 지정하고 늘어나는 비율을 두 배로 하고 싶은 항목의 flex 속성 값만 20 1 200px로 지정해도 동일하게 동작합니다.

축약형 속성 flex

보통은 flex-grow, flex-shrink, flex-basis 값을 각각 사용하지 않고 이 세 속성을 한번에 지정하는 flex 축약형을 많이 사용합니다. flex 축약형의 값은 flex-grow, flex-shrink, flex-basis 순서로 지정됩니다.

다음의 라이브 예시에서 flex 축약형의 값들을 조절하면서 시험해 볼 수 있습니다. 첫 값이 flex-grow를 지정하며, 이 첫 값을 양수로 하면 flex 항목이 넓어질 수 있습니다. 두 번째 값은 flex-shrink 를 지정하며 이 두 번째 값에 양수를 지정하면 flex 항목이 좁아질 수 있습니다. 세 번째 값은 flex-basis를 지정하며 이 값은 flex 항목이 넓어지거나 좁아질 때 고려하는 기준 값입니다.

flex 축약형 표현에 사용할 수 있는 미리 정의된 축약 값들이 아래에 나열되어 있습니다. 이 값들 만으로도 대부분의 경우(use-case)에 대응할 수 있을 것 입니다.

  • flex: initial
  • flex: auto
  • flex: none
  • flex: <positive-number>

flex 항목flex: initial로 지정하면 flex: 0 1 auto 로 지정한 것과 동일하게 동작합니다. 이 경우, flex 항목들은 flex-grow가 0이므로 flex-basis값보다 커지지 않고 flex-shrink가 1이므로 flex 컨테이너 공간이 모자라면 크기가 줄어듭니다. 또, flex-basisauto이므로 flex 항목은 주축 방향으로 지정된 크기 또는 자기 내부 요소 크기 만큼 공간을 차지합니다.

flex: auto 로 지정하면 flex: 1 1 auto로 지정한 것과 동일하며, flex:initial 과는 주축 방향 여유 공간이 있을 때 flex 항목들이 늘어나서 주축 방향 여유 공간을 채우는 점만 다릅니다.

flex: none으로 지정하면 flex: 0 0 auto으로 지정한 것과 동일하며 flex 컨테이너의 크기 변화에도 flex 항목 크기는 변하지 않고 flex-basisauto로 지정했을 때 정해지는 크기로 결정됩니다.

이 축약형은 더 축약해서 flex: 1 이나 flex: 2처럼 쓸수도 있는데, 이는 flex-grow 만 지정하고 나머지는 1 0으로 사용한다는 뜻이다. 따라서 flex: 2flex: 2 1 0와 동일하게 처리됩니다.

다음 라이브 예제에서 이 축약 값들을 시험해 볼 수 있습니다.

정렬, 끝 맞추기(justification), flex 항목간 여유 공간 분배

flexbox의 주 기능 중 하나는 (주축과 교차축으로 표현되는) flex 컨테이너 공간 안에 flex 항목들을 정렬하고 끝 마추며 여유 공간을 항목 간에 분배하는 것입니다.

역주) 이 절의 내용은 편의상 flex 컨테이너의 flex-direction를 row로 가정하고 '행'과 '열'로 표기했습니다.

align-items

align-itemsflex 컨테이너에 지정하는 속성이며, 교차축을 따라 flex 항목 열을 정렬하는 방식을 지정합니다.

이 속성의 (아무것도 지정하지 않았을 때 적용되는)초기 값은 stretch이며 이 값을 지정하면 flex 항목의 높이는 flex 컨테이너flex 항목 행의 최대 높이로 지정됩니다. 따라서, flex 항목 행이 하나 일 때는 flex 항목은 교차축 방향으로 flex 컨테이너를 가득 채우게 됩니다.

이 속성을 flex-start로 지정하면 flex 항목의 첫 열이 교차축 방향의 시작선에 정렬됩니다. flex-end로 지정하면 flex 항목의 첫 열이 교차축 방향의 끝선에 정렬됩니다. center로 지정하면 flex 항목 행에 배분된 공간의 가운데 라인에 정렬됩니다.

다음 라이브 예제에서 이 값들을 시험해 볼 수 있습니다. - 이 시험을 위해 의도적으로 flex 컨테이너에 높이를 지정해 두었습니다.

  • stretch
  • flex-start
  • flex-end
  • center

justify-content

justify-content 속성은 주축을 따라 flex 항목 행을 정렬하는 방식을 지정합니다.

이 속성의 (아무것도 지정하지 않았을 때 적용되는)초기 값은 flex-start이며 이 값을 지정하면 flex 항목 행 내의 항목들은 flex 컨테이너의 시작선에서 부터 정렬됩니다. flex-end로 지정하면 flex 항목 행의 마지막 항목이 flex 컨테이너의 끝선에서 정렬됩니다. center로 지정하면 flex 항목들이 flex 항목 행의 가운데 정렬됩니다.

space-between을 지정하면 주축 방향 여유 공간을 flex 항목 사이의 공간에 균등 배분합니다.

space-around는 시작선 및 끝선과 flex 항목간 공간도 균등 배분에 고려하므로 시작선 및 끝선과 flex 항목 간의 공간의 크기를 1로 배분한다면 flex 항목 사이의 공간은 2로 배분합니다.

space-evenly로 지정하면 여유 공간을 flex 항목 사이의 공간 및 시작선 및 끝선과 flex 항목 간의 공간에 모두 균등하게 배분합니다.

다음 라이브 예제에서 justify-content에 지정할 수 있는 다음 값들을 시험해 볼 수 있습니다.

  • stretch
  • flex-start
  • flex-end
  • center
  • space-around
  • space-between
  • space-evenly

이 절에서 설명한 내용으로 대부분의 경우에 대응할 수 있지만, Aligning Items in a Flex Container 에서 이 속성들을 더 자세히 살펴볼 것입니다.

Next steps

Flexbox의 개요를 살펴보았습니다. 다음 글 how this specification relates to other parts of CSS에서 이 규격이 다른 CSS 규격과 어떻게 연관되어 있는지 말씀드리겠습니다.