useCodeusecode logo

Flexbox 이해 - 당신이 알아야 할 모든 것

March 05, 2017

원문: Understanding Flexbox: Everything you need to know

img

이 글에서는 CSS의 Flexbox 모델에 익숙해지기 위해 필요한 모든 기본 개념에 대해 설명할 것이다. 긴 글이므로 마음의 준비가 되었기를 바란다.

.pdf로 읽고 싶다면 다운로드 링크가 있다.

presentation

기존에 CSS의 레이아웃에 대해 기존의 지식과는 많이 다르기 때문에 Flexbox를 배우는 것은 쉽지 않을 수 있다. 하지만, 배울 가치가 있는 모든 것은 이런 식으로 시작한다.

Flexbox는 중요하게 받아 들여야한다. 이것은 레이아웃을 잡는 현대적인(modern) 방식을 토대로 하고 있으며, 금방 사라지지 않을 것이다. 새로운 표준으로 부상했다. 그러니 팔을 벌려 안아 주자!

당신이 배우게 될 것

먼저 Flexbox의 기본을 살펴 보자. Flexbox 이해하는 여기서부터 시작해야한다고 생각한다.

presentation

핵심을 배우는 것은 쿨하다(cool). 더 쿨한 것은 실제 어플리케이션을 만드는데 이러한 핵심을 적용하는 것이다.

나는 “작은 것”을 많이 만드는 것을 보여 줄 것이다. 나중에는 완전히 Flexbox로 된 이 음악 앱을 만드는 것으로 글을 마무리 할 예정이다.

presentation

꽤 멋져 보이지 않는가?

음악 앱 레이아웃을 만드는 방법을 배우면서 Flexbox의 내부 동작에 대해 살펴 보겠다. 또한 Flexbox가 반응형 웹 디자인에서 어떤 역할을 하는지도 볼 수 있을 것이다.

이걸 다 보여 줄 수 있어서 기쁘다.

presentation

유저 인터페이스를 작성하기 전에 먼저 몇 가지를 보여줄 것이다. 지루할 수도 있지만 Flexbox에 능숙해지는 과정의 일부이다.

시작해보자.

소개

presentation

CSS는 지난 몇 년 동안 많은 발전을 했다. 디자이너는 필터(filters), 트랜지션(transitions) 및 트랜스폼(transforms)이 추가된 것에 기뻐했다. 그러나 뭔가가 빠져있었다. 우리 모두가 원했던 것.

Crafting Intelligent 페이지 레이아웃은 CSS를 사용하여 너무 오랫동안 지속되는 것처럼 보였으며, 많은 사람들이 해킹 된 CSS를 작성했다.

우리는 매번 float, table display 핵(hack) 등을 다뤄야했다. CSS를 작성 해본 적이 있다면 아마 이런 경험이 있을 것이다. 만약 아니라면, 더 나은 세상에 오신 것을 환영한다!

마침내 디자이너와 프론트엔드 개발자들의 염원을 들어준 것처럼 보인다.

이제 우리는 CSS 속임수를 버릴 수 있다. 더 이상 플롯(float), 테이블 셀(table-cell) 디스플레이를 사용하지 않아도된다.

Crafting intelligent 레이아웃을 제작하기 위해 보다 깨끗하고 현대적인 구문을 채택 할 때다. CSS Flexbox 모델에 온것을 환영한다.

Flexbox란?

스펙(specification)에 따르면 Flexbox 모델은 뷰포트(viewport) 및 엘리먼트 (elemnt) 크기가 동적이거나 알려지지(unknown) 않은 경우에도 문서 내의 엘리먼트간에 공간을 배치(layout), 정렬(align) 및 분산(distribute)하는 효율적인 방법을 제공한다.

너무 포멀(formal)하게 들릴 수 있다. 잠시 후, 이것이 무엇을 의미하는지 쉽게 이해할 수 있도록 설명 할 것이다.

당신이 꿈 속에서 CSS를 작성하든, 아니면 막 시작하든 간에, 집에있는 것처럼 편안하게 느낄 것이다.

Flexbox 모델을 사용하려면 어떻게해야할까?

이것은 모든 사람이 묻는 첫 번째 질문이며, 그 대답은 예상했던 것보다 훨씬 간단하다.

Flexbox 모델을 사용하려면 먼저 flex-container를 정의해야한다.

일반 HTML에서 간단한 목록을 만드는 것은 다음과 같이 할 수 있다.

<ul>
  <!--parent element-->
  <li></li>
  <!--first child element-->
  <li></li>
  <!--second child element-->
  <li></li>
  <!--third child element-->
</ul>

코드를 보면, ul 태그가 li 태그를 포함하고 있다.

ul을 부모 엘리먼트, li을 자식 엘리먼트라고 부른다.

Flexbox 모델을 사용하려면 부모 엘리먼트를 flex container (flexible container로 알려진)로 만들어야한다.

display: flex 또는 display: inline-flex를 설정하면 된다. 정말 간단하지 않은가. 이제 Flexbox 모델을 사용하도록 설정되었다.

실제로 일어나는 일은 Flexbox 포맷 컨텍스트가 즉시 시작(initiated)되는 것이다.

생각보다 어렵지 않다고 내가 얘기하지 않았는가.

presentation

정렬되지 않은 목록(ul)과 목록(li) 엘리먼트를 사용하여 Flexbox 포맷 컨텍스트를 구성하는 방법은 아래와 같다.

/*Make parent element a flex container*/
ul {
  display: flex; /*or inline-flex*/
}

li 엘리먼트에 스타일을 추가한다.

li {
  width: 100px;
  height: 100px;
  background-color: #8cacea;
  margin: 8px;
}

아래와 같은 결과를 볼 수 있을 것이다.

presentation

눈치 채지 못했겠지만, 이미 어떤 일이 벌어졌다. 이제 Flexbox 포맷 컨텍스트가 시작됐다.

기본적으로 CSS 스택의 “divs”는 위에서 아래로 다음과 같이 수직으로(vertically) 저장된다는 것을 기억하자.

presentation

위의 이미지가 당신이 예상한 결과일 것이다.

그러나 여기에 display: flex를 추가하면 레이아웃이 변경 되는 것을 즉시 볼 수 있다.

이제 목록 요소(li)는 왼쪽에서 오른쪽으로 가로로 쌓인다. 당신이 기존에 float을 사용하여 만들었던 것처럼.

presentation

FlexBox 모델은 모든 상위 요소에 ”flex display“를 추가하자마자 동작한다.

목록 요소의 방향 변경이 왜 발생했는지 이해하지 못할 수도 있다. 곧 자세히 설명하도록 하겠다. 하지만 지금은 그저 따라와 주길 바란다.

flex display“를 선언하면 Flexbox 모델이 시작된다.

주의를 기울여야 할 한가지가 더 있다.

display 속성을 flex로 설정하면 정렬되지 않은 목록(ul)이 자동으로 flex container가 되고 자식 엘리먼트 (이 경우 li)가 flex items가 된다.

Flexbox 모델에 좀 더 재밌는 것들을 설명하게 되면, 이 용어는 반복해서 나타난다.

두 가지 핵심 단어를 사용했는데 이것에 더 중점을 두고 설명하고 싶다. 이것은 앞에 놓인 것을 이해하는데 매우 중요하다.

  1. Flex container: display: flex를 설정 한 부모 엘리먼트
  2. Flex items : Flex container 내의 자식 엘리먼트

presentation

이건 Flexbox 모델을 사용하기위한 기초다.

Flex Container 프로퍼티(Properties)

Flex-direction || Flex-wrap || Flex-flow || Justify-content || Align-items || Align-content

presentation

위의 섹션에서 몇 가지 기본 원칙을 설명했다. flex-containersflex-items는 무엇이고, Flexbox 모델을 어떻게 시작 할 수 있는지.

이제는 잘 활용할 시간이다.

부모 엘리먼트를 flex container로 설정하면, 두 가지 정렬 속성을 사용할 수 있다.

블록 요소의 너비 속성을 width: 200px로 정의하는 것처럼 flex container에는 6 가지 속성이 있다.

좋은 소식은 이러한 속성을 정의 할 때 이미 익숙했던 것과 다른 방식을 요구하지 않는다는 것이다.

1. Flex-direction

flex-direction 속성은 플렉스 아이템들(flex-items)이 주축(main axis)을 따라 배치되는 방향을 제어한다.

4 가지 값 중 하나를 가질 수 있다.

/* 여기서 ul은 플렉스 컨테이너를 나타낸다. */
ul {
  flex-direction: row || column || row-reverse || column-reverse;
}

일반적으로, flex-direction 속성은 플렉스 아이템이 배치되는 방향을 결정 한다. 수평(horizontally), 수직(vertically), 또는 양방향의 반대(reversed) 방향.

기술적으로, “수평(horizontal)“과 “수직(vertical)“은 “flex 세상”에서는 올바른 용어가 아니다.

이것은 주축(main axis)과 교차 축(cross axis)으로 불린다. 기본값은 아래와 같다.

일반적으로, 주축의 기본 방향은 왼쪽에서 오른쪽으로 배치되는 “수평”과 같이 느껴진다.

교차 축은 위에서 아래로 배치되는 “수직”과 같다.

presentation

기본적으로 flex-direction 속성은 (row)으로 설정되고 주축을 따라 플렉스 아이템을 정렬한다. 이것은 이 글의 시작 부분에서 정렬되지 않은 목록(ul)을 정렬 방식을 설명한다.

flex-direction 속성이 명시적으로 설정되지 않았더라도 기본값인 (row)을 사용 한다.

플렉스 아이템은 왼쪽에서 오른쪽 수평 방향으로 채워진다.

![presentation](./0-SG-1eH7jnCkG3WP2 (1).png)

flex-direction 속성이 (column)로 변경되면 플렉스 아이템이 교차 축을 따라 정렬된다.

그들은 왼쪽에서 오른쪽으로가 아니라 위에서 아래로 채워진다.

presentation

2. Flex-wrap

flex-wrap 속성은 다음 세 가지 값 중 하나를 가질 수 있다.

/* 여기서 ul은 플렉스 컨테이너를 나타낸다 */
ul {
  flex-wrap: wrap || no-wrap || wrap-reverse;
}

flex-wrap 속성이 예제를 통해 어떻게 작동하는지 설명하겠다.

정렬되지 않은 목록(ul)에 더 많은 아이템을 추가해보자.

어떻게 될 것이라고 생각하는가? 플렉스 컨테이너에 더 많은 아이템이 추가된다면 크기가 조정되거나 다른 줄로 나뉠까?

/* li 엘리먼트 3 개 추가 */
<ul>
  <!--parent element-->
  <li></li>
  <!--first child element-->
  <li></li>
  <!--second child element-->
  <li></li>
  <!--third child element-->
  <li></li>
  <li></li>
  <li></li>
</ul>

다행히도, 플렉스 컨테이너는 새로 추가된 플렉스 아이템을 조정한다.

presentation

조금더 나가보자.

말도 안되는 양의 플렉스 아이템을 부모 요소에 추가하자. 총 10 개의 아이템으로 만든다.

어떻게 됐는가?

presentation

다시 말하지만, 플렉스 컨테이너는 브라우저를 가로로 스크롤해야하는 경우에도 모든 자식 요소에 맞게 조정한다.

이것은 모든 플렉스 컨테이너의 기본 동작이다. 플렉스 컨테이너는 더 많은 플렉스 아이템을 한 줄에 계속해서 나열한다.

flex-wrap 속성의 기본값은 no-wrap이다. 이로 인해 플렉스 컨테이너가 랩핑되지 않는다.

ul {
  flex-wrap: no-wrap;
  /*Keep on taking more flex items without breaking (wrapping)*/
}

no-wrap값은 변경할 수 있다.

만약 많은 수의 플렉스 아이템이 있다면, 플렉스 아이템을 플렉스 컨테이너 내에 “랩(wrap)“하고 싶을 것이다.

“Wrap”은 플렉스 컨테이너 내의 사용 가능한 공간이 플렉스 아이템을 기본 너비로 더이상 포함할 수 없으면 여러 줄로 나뉘어진다.

이것은 wrap 값으로 가능하다.

presentation

한 가지 값이 더 있다.

그래, 맞다. 플렉스 아이템이 반대(reverse) 방향 여러 라인으로 나뉘어 진다.

presentation

3. Flex-flow

flex-flowflex-directionflex-wrap 값의 약칭 속성이다.

border 약칭 속성을 사용한 적이 있는가? border: 1px solid red.

이것은 같은 개념이다. 여러 값이 한 행에 선언되었다.

아래 예제를 참고하자.

ul {
  flex-flow: row wrap; /*direction "row" and yes, please wrap the items.*/
}

presentation

다른 조합을 시도해자. flex-flow: row wrap, flex-flow: column wrap, flex-flow: column no-wrap

생성 된 결과는 flex-directionflex-wrap 값에서 본 것과 다르지 않다.

이것의 어떻게 될지 분명 알 수 있을것이다.

한번 시도해보자.

4. Justify-content

Flexbox 모델은 정말 좋다. 여전히 그것을 의심한다면, justify-content 속성을 보면 확신할 수 있을 것이다.

justify-content 속성은 아래의 5 가지 값 중 하나를 갖는다.

ul {
  justify-content: flex-start || flex-end || center || space-between ||
    space-around;
}

justify-content 속성이 정확히 무엇일까?

음,아마 text-align 속성을 떠올릴 수도 있다.

justify-content 속성은 주축(main axis)에서 플랙스 아이템을 배치하는 방법을 정의한다.

간단한 예제를 보자.

아래의 간단한 ul을 보자.

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

기본적인 스타일을 추가해보자.

ul {
  border: 1px solid red;
  padding: 0;
  list-style: none;
  background-color: #e8e8e9;
}
li {
  background-color: #8cacea;
  width: 100px;
  height: 100px;
  margin: 8px;
  padding: 4px;
}

아래와 같을 것이다:

presentation

justify-content 속성을 사용하면 세개의 플렉스 아이템이 속성을 정의한대로 주축(main axis)을 기준으로 정렬 된다.

다음과 같이 속성을 정의 할 수 있다.

(i) Flex-start

기본값은 flex-start이다.

flex-start는 모든 flex-items를 주축(main axis)의 시작 부분으로 그룹화한다.

ul {
  justify-content: flex-start;
}

presentation

(ii) Flex-end

flex-end는 flex-items를 주축(main axis)의 으로 그룹화한다.

ul {
  justify-content: flex-end;
}

presentation

(iii) Center

center는 예상하는 대로이다. 즉, flex-items를 주축(main axis)을 따라 중앙에 배치한다.

ul {
  justify-content: center;
}

presentation

(iv) Space-between

space-between은 각 플렉스 항목간에 동일한 간격(space)을 유지한다.

ul {
  justify-content: space-between;
}

presentation

음, 여기 다른 점을 눈치 챘는가?

아래 이미지를 보자.

presentation

(v) Space-around

마지막으로, space-around은 flex-items 주위에 동일한 간격을 유지한다.

ul {
  justify-content: space-around;
}

presentation

아래 이미지의 설명을 참고하자.

presentation

너무 많은 것 같더라도 걱정하지 말자. 조금만 연습하면 문법에 금방 익숙해질 것이다.

주축(main axis)을 따라 플렉스 아이템이 어떻게 배치되는지 확실히 이해해야한다.

5. Align-items

align-items 속성은 justify-content 속성과 다소 비슷하다.

justify-content 속성을 이해하면 금방 이해할 수 있을 것이다.

align-items은 다음 값 중 하나를 가질 수 있다. flex-start || flex-end || center || stretch || baseline

/* ul represents any flex container*/
ul {
  align-items: flex-start || flex-end || center || stretch || baseline;
}

플렉스 아이템이 교차 축(cross axis)에 배치되는 방법을 정의한다. align-items 속성과 justify-content의 차이점이다.

다음은 이런 다양한 값이 플렉스 아이템에 미치는 영향이다.

교차 축을 기준으로 이러한 속성 값이 어떤 영향을 주는지 주의깊게 확인하자.

(i) Stretch

기본값은 stretch이다. 이것은 플렉스 아이템이 플렉스 컨테이너의 전체 높이를 채울 수 있도록 플렉스 아이템을 “늘린다(stretch)“.

presentation

(ii) Flex-start

flex-start는 예상하는 대로다. 플렉스 아이템을 교차 축의 시작 부분에 그룹화한다.

presentation

(iii) Flex-end

예상대로 flex-end는 플렉스 아이템을 교차 축의 끝으로 그룹화한다.

presentation

(iv) Center

center 값은 똑같이 예측 가능하다. 플렉스 아이템의 중심에 플렉스 아이템을 정렬한다.

presentation

(v) Baseline

그렇다면 baseline 값은?

베이스라인(baselines)을 따라 플렉스 아이템을 정렬한다.

presentation

baseline“은 왠지 좀 복잡해 보인다.

결과는 flex-start처럼 보일 수 있지만 미묘하게 다르다.

도대체 ”baseline“이란 무엇일까?

아래 이미지가 도움이 될 것이다.

presentation

모든 플렉스 아이템이 “baseline”에 맞춰서 정렬되어 있는 것을 확인하자.

6. Align-content

위에서 wrap 속성을 다룰 때, 플렉스 컨테이너에 더 많은 플렉스 아이템을 추가하면 어떤 일이 일어나는지 기억하는가?

multi-line 플렉스 컨테이너가 된다.

align-content 속성은 multi-line 플렉스 컨테이너에서 사용된다.

baseline을 제외하곤 align-items과 동일한 값을 사용한다.

의미상으로, 이것은 multi-line 플렉스 컨테이너에서 플렉스 아이템이 정렬되는 방법을 컨트롤 한다.

align-items과 마찬가지로 기본값은 stretch이다.

친숙해져야 할 값들이다. 그렇다면, 10개의 플렉스 아이템이 있는 multi-line 플렉스 컨테이너에 어떻게 영향을 미치는지 알아보자.

(i) Stretch

stretch를 사용하면, 플렉스 아이템은 교차 축을 따라 사용 가능한 공간에 맞게 “늘어난다(stretched)“.

아래 플렉스 아이템 사이에 보이는 간격은 아이템에 설정된 margin 때문이다.

presentation

(ii) Flex-start

위에서 이미 flex-start 값을 봤다.

이번에는 multi-line 컨테이너의 아이템을 교차 축의 시작 부분에 정렬한다.

교차 축은 기본적으로 위에서 아래로 정렬되는 거을 기억하자.

따라서, 플렉스 아이템은 플렉스 컨테이너의 상단(top)에 정렬된다.

presentation

(iii) Flex-end

flex-end 값은 플렉스 아이템을 교차 축의 끝에 정렬한다.

presentation

(iv) Center

짐작 하듯이 center는 플렉스 아이템을 교차 축의 중심(center)에 정렬한다.

presentation

이것이 플렉스 컨테이너의 마지막 속성이다.

이제 다양한 플렉스 컨테이너 속성을 사용하는 방법을 이해했을 것이다.

Flex Item Properties

Order || Flex-grow || Flex-shrink || Flex-basis

presentation

이전 섹션에서는 플렉스 컨테이너(flex-container)와 정렬(alignment) 속성에 대해 설명했다.

정말로 아름답다.

앞으로 설명해야 할 것이 어떤 것일지 짐작 할 것이다.

이제 플렉스 컨테이너에서 벗어나 플렉스 아이템과 이것의 정렬 속성을 살펴 보겠다.

플렉스 컨테이너와 마찬가지로 몇 가지 정렬 속성은 플렉스 아이템에서도 사용할 수 있다.

하나씩 차근차근 알아보자.

1. Order

order 속성을 사용하면 컨테이너 내의 플렉스 아이템을 재정렬(reordering) 할 수 있다.

기본적으로 order 속성을 사용하면 플렉스 아이템을 한 위치에서 다른 위치로 이동할 수 있다. ”sortable” 리스트처럼 할 수 있다는 것이다.

HTML 코드와는 상관없이 이뤄진다. 즉, HTML 소스 코드에서 플렉스 아이템의 위치가 변경되지 않는다.

order 속성의 기본값은 0이다. 음수 또는 양수 값을 가질 수 있다.

플렉스 아이템은 order 속성의 숫자 값을 기반으로 재배열된다는 점을 유의하자. 최저 값(lowest)에서 최고 값(highest)까지.

아래의 정렬되지 않은 목록(unordered list) 예제를 살펴보자:

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

기본적으로 플렉스 아이템의 order 값은 모두 0이다.

예상한대로, 기본적인 스타일링을 추가하면 아래와 같다.

presentation

플렉스 아이템은 HTML 소스 순서대로 표시된다. 플렉스 아이템 1, 2, 3, 4.

만약 어떤 이유로 HTML 소스를 변경하지 않고 플렉스 아이템의 첫번째 아이템이 마지막에 나타나기를 원한다면?

여기서 ”소스를 변경하지 않고“는 이 아래를 의미한다:

<ul>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>1</li>
</ul>

여기서 order 속성이 필요한 것이다.

플렉스 아이템 1의 order 값을 다른 리스트 아이템보다 높게 만들기만 하면 된다.

블록 엘리먼트에 z-index 속성을 사용한 적이 있다면 이런 종류의 것을 잘 알고있을 것다.

/*select first li element within the ul */
li:nth-child(1) {
  order: 1; /*give it a value higher than 0*/
}

플렉스 아이템은 가장 낮은 값에서 가장 높은 값 순으로 재배열 된다.

기본적으로 리스트 아이템 2, 3, 4의 순서 값은 모두 0임을 잊지 말자.

이제 플렉스 아이템 1의 order 값은 1이 됐다.

presentation

플렉스 아이템 2, 3, 4의 order 값은 모두 0이다. HTML 소스는 변경없이 그대로이다.

플렉스 아이템 2에 2의 order 값을 주면 어떻게 될까?

그렇다. 이것은 스택(stack)도 올라간다. 이제는 플렉스 아이템 2가 가장 높은 order 값을 나타낸다.

presentation

그렇다면, 두 플렉스 아이템의 order 값이 같은 경우는 어떻게될까?

아래 예제에서 플렉스 항목 1과 3에는 동일한 order 값을 넣어보자.

li:nth-child(1) {
  order: 1;
}
li:nth-child(3) {
  order: 1;
}

presentation

아이템은 여전히 낮은 값에서 높은 값으로 배열된다.

이번에는 플렉스 아이템 3이 소스 파일 (HTML 문서)에서 플렉스 아이템 1 다음에 위치하기 때문에 마지막으로 배치된다.

재배열(re-ordering)은 두 개 이상의 플렉스 아이템의 순서 값이 같을 때 소스 파일의 위치를 기반으로한다.

충분히 설명한 것 같다.

다른 속성으로 넘어가 보자.

2. flex-grow and flex-shrink

플렉스 아이템의 장점은 “유연함”에 있다.

flex-growflex-shrink 속성 덕분에 이 “유연함”을 더욱 효과적으로 활용할 수 있다.

flex-growflex-shrink 속성은 여분의 공간이 있다면 플렉스 아이템을 “확장(grow)” 해야하는지, 또는 여분의 공백이 없다면 “축소(shrink)“해야 하는지를 제어한다.

0에서 임의의 양수의 값을 가질 수 있다. 0 || 정수

이해하기 쉽게 설명 하도록 하겠다.

아래의 간단한 정렬되지 않은 목록을 보자. 딱 하나의 목록 아이템만 가지고 있다.

<ul>
  <li>I am a simple list</li>
</ul>
ul {
  display: flex;
}

스타일을 조금 추가하면 이런 모습이 된다.

presentation

기본적으로 flex-grow 속성은 0으로 설정된다. 즉, 플렉스 아이템은 사용 가능한 전체 공간에 맞게 확장되지 않는다.

값 0은 “끄기” 스위치라고 할 수 있다. flex-grow 스위치가 꺼져있는 것이다.

그러나 flex-grow 값을 1로 변경하면 다음과 같은 결과가 된다.

presentation

플렉스 아이템은 현재 사용 가능한 공간을 모두 차지하기 위해 “확장된다(grow)“. 스위치가 켜진 것이다!

브라우저를 리사이즈하면 플렉스 아이템이 새 화면 너비에 맞게 “축소(shrink)” 된다.

왜일까? 기본적으로 shrink 속성은 1로 설정되기 때문이다. 이는 flex-shrink 스위치가 켜져 있음을 의미한다!

여러분이 이것에 대해 확실하게 이해하지 못했다면, 잠시 후에 flex-growflex-shrink 속성을 좀 더 자세히 살펴보도록 할 것이다.

3. flex-basis

플렉스 아이템의 장점이 “유연함”에 있다고 말한 것을 기억 하는가?

flex-grow 또는 flex-shrink 속성이 컨테이너에 맞게 크기를 조정하기 전에 flex-basis 속성은 플렉스 아이템의 초기 크기를 지정한다.

방금 언급한 것은 정말로 중요하다. 그래서 이것을 확실하게 집고 넘어가기 위해 조금더 시간을 할애하도록 하겠다.

기본값은 flex-basis: auto다. flex-basis 일반적인 너비(width) 속성에서 사용하는 모든 값을 취할 수 있다. 즉, percentages(%) || ems || rems || pixels

basis 속성을 0으로 설정하려고 할 때도 단위(unit)를 사용하는 것에 주목하자. flex-basis: 0이 아닌 flex-basis: 0px로 사용해라.

다시 “하나의 목록”예제를 사용 하겠다.

<ul>
  <li>I am a simple list</li>
</ul>
ul {
  display: flex;
}
li {
  padding: 4px; /*some breathing space*/
}

기본적으로 플렉스 아이템의 초기 너비는 기본값인 flex-basis: auto의 영향을 받는다.

플렉스 아이템의 너비는 컨텐츠 크기에 따라 “자동”으로 계산된다 (당연히, 패딩도 포함된다).

presentation

즉, 플렉스 아이템의 컨텐츠를 늘리면 자동으로 크기가 조정된다.

<ul>
  <li>I am a simple list AND I am a simple list</li>
</ul>

presentation

그러나 플렉스 아이템을 고정 너비로 설정 하려면 다음과 같이하면 된다:

li {
  flex-basis: 150px;
}

이제 플렉스 아이템 너비는 150px로 제한되었다.

presentation

점점 더 재미있어지고 있지 않은가.

4. flex shorthand

flex shorthand는 flex-grow, flex-shrinkflex-basis 속성을 한꺼번에 설정할 수 있게한다.

필요한 경우, 개별적으로 선언하는 것보다 flex shorthand를 사용하여 세 가지 속성을 모두 한꺼번에 설정하는 것이 좋다.

li {
  flex: 0 1 auto;
}

위의 코드는 이 세 가지 속성을 설정하는 것과 같다. flex-grow: 0; flex-shrink: 1; flex-basis: auto

순서에 주의하자.

먼저 flex-grow 후에 flex-shrinkflex-basis. 줄여서 쓴다면 GSB가 도움이 될 수 있다.

flex-shorthand에 값 중 하나를 설정하지 않으면 어떻게될까?

flex-growflex-shrink 값만 설정하면 flex-basis는 기본값인 0이 된다.

이것을 absolute flex라고 한다. flex-basis만 설정하면 relative flex가 된다.

/*이것이 absolute flex item이다.*/
li {
  flex: 1 1; /*flex-basis defaults to 0*/
}
/*이것이 relative flex item이다.*/
li {
  flex-basis: 200px; /*only flex-basis is set*/
}

그렇다면, relativeabsolute 플렉스의 목적은 무엇일까?

이 글의 뒷부분에서 이 질문에 답하도록 하겠다. 지금은 나를 믿고 계속 따라와주길 바란다.

매우 유용한 flex shorthand 값을 살펴 보자.

1. flex: 0 1 auto

/*다시, "li"는 flex-item을 나타낸다.*/
li {
  flex: 0 1 auto;
}

이는 flex: default를 작성하는 것과 동일하며 모든 플렉스 아이템의 기본 값이다.

여기의 값들을 풀어 헤쳐보자.

presentation

flex-basis 속성을 먼저 보면 더 쉽게 이해 할 수 있을 것이다.

flex-basisauto로 설정된다. 즉, 플렉스 아이템의 초기 폭은 내용의 크기에 따라 자동으로 결정된다.

다음으로 flex-grow 속성 값은 0이다. 이것은 flex-grow 속성이 플렉스 아이템의 초기 폭을 변경하지 않는다는 것을 의미한다.

확장(grow) 스위치가 꺼져 있는 것이다.

flex-grow는 플렉스 아이템의 “확장(grow)“을 제어하고 0으로 설정되기 때문에 플렉스 아이템은 화면에 맞게 “커지지” 않는다.

마지막으로, flex-shrink 값은 1이다.이 말은 - “필요하다면 플렉스 아이템을 줄인다(shrink)“와 같다.

다음은 플렉스 아이템에 적용했을 때의 모습이다.

presentation

플렉스 아이템이 늘어나지(grow) 않는 것에 주목하자. 폭은 자동으로 계산되며 브라우저 크기를 조정하면 줄어든다(shrink).

2. flex: 0 0 auto

/*again, the "li" represents any list-item*/
li {
  flex: 0 0 auto;
}

이것은 flex: none과 같다.

앞에서 설정한 동일한 프레임워크를 사용하면 폭은 자동으로 계산되지만 플렉스 아이템은 확대(grow)되거나 축소(shrink)되지 않는다 (둘 다 0으로 설정 됨).

확대 및 축소 스위치는 모두 꺼져 있다.

그것은 기본적으로 초기(initial) 폭이 플렉스 아이템의 컨텐츠 크기를 기반으로하는 고정 너비 엘리먼트이다.

이 flex shorthand가 두 플렉스 아이템에 어떻게 영향을 미치는지보자. 컨텐츠 길이가 길어지면 플렉스 아이템의 폭도 넓어진다.

presentation

가장 먼저 주목해야 할 점은 플렉스 아이템의 폭이 서로 다르다는 것이다.

이는 컨텐츠 크기에 따라 너비가 자동으로 계산되기 때문이다.

브라우저의 크기를 조정해도 플렉스 아이템의 너비가 줄어들지 않는다는 것을 확인 할 수 있다. 플렉스 아이템이 부모 엘리먼트를 벗어나게 되서, 컨텐츠를 보려면 브라우저를 가로로 스크롤해야한다.

걱정하지 말자. 나중에 이러한 이상한 행동을 어떻게 처리 할 수 있는지 보여주도록 하겠다.

presentation

3. flex: 1 1 auto

이것은 flex: auto와 동일하다.

앞서 설정 한 프레임워크를 사용하자.

이것은 “자동으로 초기 너비를 계산하지만 사용 가능한 전체 공간에 맞게 증가(grow)하고 필요한 경우 축소(shrink)된다”는 것을 의미한다.

확대 및 축소 스위치가 켜지고 너비가 자동으로 계산된다.

presentation

이번에는 플렉스 아이템이 사용 가능한 공간을 가득 채우고 브라우저의 크기를 줄이면 따라서 축소된다.

4. flex: “양수”

여기서 “양수(positive number)“는 양수를 나타낸다 (따옴표 제외)

이것은 flex: “양수” 1 o과 같다.

flex: 2 1 0flex: 2와 같다. 여기서 2는 양수를 나타낸다.

/* 다시 말하지만, "li"는 리스트 아이템을 나타낸다. */
li {
  flex: 2 1 0; /*flex: 2와 같다.*/
}

앞에서 설정한 프레임워크와 마찬가지로 플렉스 아이템의 초기 너비를 0으로 설정하고 사용 가능한 공간을 채우도록 아이템을 늘린 다음 가능한 경우 아이템을 축소한다.

플렉스 아이템에 “폭(width)이 없는” 경우 폭은 어떻게 계산될까?

flex-grow 값에 따라 플렉스 아이템이 “확장(widen)“되는 정도를 결정한다.

이것은 플렉스 아이템의 너비가 없는 문제를 처리한다.

플렉스 아이템이 두 개 이상일 때 플렉스 아이템의 초기 폭, flex-basis가 0을 기준으로하는 값(예를들어, 0px)으로 설정되어있는 경우라면 이 flex shorthand를 사용하는 것이 더 실용적이다.

실제로는 플렉스 아이템의 너비가 flex-grow 값의 비율에 따라 계산된다.

아래에 두 개의 리스트 아이템을 보자.

<ul>
  <li>I am One</li>
  <li>I am Two</li>
</ul>
ul {
  display: flex;
}
/*first flex-item*/
li:nth-child(1) {
  flex: 2 1 0; /*same as just writing flex: 2*/
}
/*second flex-item*/
li:nth-child(2) {
  flex: 1 1 0;
  background-color: #8cacea;
}

flex-grow: 1로 설정하면 플렉스 아이템이 사용 가능한 공간을 채운다. 확대 스위치가 켜져 있는 것이다.

만약에 두 가지 플렉스 아이템이 있다고 생각해보자. 하나는 flex-grow 속성이 1이고 다른 하나는 2라면 어떻게 될까?

두 항목 모두에 대해 확대 스위치가 켜져 있는 것이다. 그러나 확대될 크기는 1과 2로 다르다.

둘 다 사용 가능한 공간을 채우기 위해 확장되지만 어느 정도의 비율로 확장이 될 것이다.

다음은 동작 방식이다.

후자는 사용 가능한 공간의 2/3을 차지하지만 전자는 1/3을 차지한다.

기본적인 비율(ratio) 값이다. 개별 비율을 총 비율로 나눈 값으로 확대 된다. 개별 비율/총 비율

presentation

무슨 일이 일어나고 있는지 보이는가?

두 플렉스 아이템은 거의 같은 크기의 컨텐츠를 가지고 있지만, 다른 공간을 차지한다.

컨텐츠 크기를 기반으로 하지않고 확대(grow) 값을 기반으로 폭이 계산된다.

앞의 플렉스 아이템의 크기는 다음 컨텐츠의 두 배에 해당한다.

5. align-self

align-self 속성은 플렉스 아이템을 더 세밀하게 컨트롤 할 수 있도록 한다.

우리는 align-items 속성으로 플렉스 컨테이너 내의 모든 플렉스 아이템을 일괄적으로 정렬하는데 사용 되는 것을 위에서 확인 했다.

인접한(neighboring) 플렉스 아이템에 영향을주지 않고, 단일 플렉스 아이템의 위치를 교차 축(cross-axis)을 따라 변경하고자 한다면 어떻게해야할까?

이것은 align-self 속성을 이용하면 된다.

이 속성은 다음 값 중 하나를 가질 수 있다: auto || flex-start || flex-end || center || baseline || stretch

/*첫 번째 리스트 아이템 대상*/
li:first-of-type {
  align-self: auto || flex-start || flex-end || center || baseline || stretch;
}

이것들은 이미 알고있는 값 들이다. 하지만, 이 값들이 특정 아이템에 어떻게 영향을 주는지 다시 한 번 생각해보자.

이 경우 컨테이너 내의 첫 번째 아이템이다.

타겟 플렉스 아이템은 빨간색이다.

1. flex-end

flex-end는 타겟 아이템을 교차 축의 끝에 정렬한다.

presentation

2. center

center는 타겟 아이템을 교차 축의 중심에 맞춘다.

presentation

3. stretch

stretch는 교차 축을 따라 사용 가능한 공간을 채우기 위해 타겟 플렉스 아이템을 “늘린다”.

presentation

4. baseline

baseline은 기준선을 따라 타겟 플렉스 아이템을 정렬한다.

그것은 flex-start와 같이 보이지만 기준선이 무엇인지 이해하고있을 것이다.

기준선에 대해서는 이미 위에서 다뤘다.

presentation

5. auto

auto는 타겟에 지정된 플렉스 아이템의 값을 부모의 align-items 값으로 설정하거나 엘리먼트에 부모가없는 경우 늘린다(stretch).

아래의 경우, 플렉스 컨테이너는 flex-startalign-items 값을 갖는다.

이렇게하면 모든 플렉스 아이템이 교차 축의 시작에 정렬된다.

이제 타겟 플렉스 아이템은 flex-start 값, 즉 부모의 align-items 값을 상속받는다.

presentation

아래의 소스는 위에서 사용 된 플렉스 아이템의 기본 스타일이다.

ul {
  display: flex;
  border: 1px solid red;
  padding: 0;
  list-style: none;
  justify-content: space-between;
  align-items: flex-start; /*affects all flex-items*/
  min-height: 50%;
  background-color: #e8e8e9;
}
li {
  width: 100px;
  background-color: #8cacea;
  margin: 8px;
  font-size: 2rem;
}

이제 당신은 재미있는 부분을 다룰 준비가 됐다. :-)

Absolute 와 Relative flex-items

presentation

이번 섹션을 들어가기전에, 몇 가지 중요한 개념을 분명히 해야 할 것 같다.

절대적(absolute) 및 상대적(relative) 플렉스 아이템의 차이점은 무엇일까?

이 둘의 주요 차이점은 간격(spacing)과 계산(computed) 방법에 있다.

상대적 플렉스 아이템(relative flex item)의 간격은 컨텐츠 크기에 따라 계산된다. 절대적 플렉스 아이템(absolute flex item)에서는 컨텐츠와 상관없이 “플렉스(flex)“에만 기반한다.

아래 마크업을 참고하자.

<ul>
  <li>
    This is just some random text to buttress the point being explained. Some
    more random text to buttress the point being explained.
  </li>
  <li>This is just a shorter random text.</li>
</ul>

두 개의 리스트 아이템. 하나는 다른 텍스트보다 훨씬 많은 텍스트가 있다.

스타일을 조금 추가하자.

ul {
  display: flex; /*flexbox activated*/
}
li {
  flex: auto; /*remember this is same as flex: 1 1 auto;*/
  border: 2px solid red;
  margin: 2em;
}

결과는 다음과 같다.

presentation

이미 잊어버렸다면 flex: 1 1 autoflex-grow: 1; flex-shrink: 1; flex-basis: auto과 같다.

앞에서 설정한 프레임워크를 기반으로 플렉스 아이템의 초기 폭이 자동으로 flex-basis: auto로 계산 된 다음 공간에 맞게(flex-grow: 1) “늘어(grow)“난다.

플렉스 아이템의 너비가 자동으로 계산되는 경우(flex-basis: auto)에는 플렉스 아이템에 포함 된 내용의 크기를 기반으로한다.

위 예의 플렉스 아이템은 같은 크기의 컨텐츠가 아니기 때문에, 플렉스 아이템의 크기는 동일하지 않을 것이다.

개별 너비는 처음부터 동일하지 않았기 때문에 (컨텐츠를 기반으로 함) 아이템이 커지면 폭도 동일하게 유지되지 않는다.

위 예의 플렉스 아이템은 상대적 플렉스 아이템이다.

플렉스 아이템을 절대적으로 만들어 보자 - 이번에는 폭이 “플렉스(flex)“가 아닌 컨텐츠 크기를 기반으로해야 함을 의미한다.

li {
  flex: 1; /*same as flex: 1 1 0*/
}

결과를 보자:

presentation

두 플렉스 아이템의 폭이 같은 것이 보이는가?

플렉스 아이템의 초기 폭은 flex-basis: 0, 그리고 “확장(grow)“가능한 공간에 맞게 늘어났다.

flex-basis 값이 0 인 플렉스 아이템이 2 개 이상있는 경우에는 flex-grow 값을 기반으로 사용 가능한 간격을 공유한다.

이것은 위에서 이미 다뤘으니 참고하자.

이제 폭은 컨텐츠 크기에 따라 계산되지 않는다. 폭은 지정된 플렉스 값을 기반으로한다.

이제 이해 되었는가?

절대적 플렉스 아이템(absolute flex item)은 플렉스(flex)만을 기반으로하는 너비를 갖지만 상대적 플렉스 아이템(relative flex item)은 컨텐츠 크기를 기준으로 너비를 갖는다.

Auto-margin Alignment

presentation

플렉스 아이템에서 ₩margin: auto₩ 정렬을 주의하자.

플렉스 아이템에 margin: auto를 사용하면 매우 이상하게 보일 수 있다.

무슨 일이 일어나는지 정확히 이해할 필요가 있다.

플렉스 아이템에서 margin: auto를 사용하면 ₩auto₩ 값을 갖는 방향 (왼쪽, 오른쪽 또는 양쪽 모두)으로 빈 공간을 채운다.

쉽게 이해 안될 수 있다.

자세히 설명 하도록 하겠다.

다음과 같이 스타일이 지정된 네비게이션 바(navigation bar)가 있다고 생각해보자.

<ul>
  <li>Branding</li>
  <li>Home</li>
  <li>Services</li>
  <li>About</li>
  <li>Contact</li>
</ul>
ul {
  display: flex;
}
li {
  flex: 0 0 auto;
}

아래의 결과를 보자.

presentation

유의해야 할 점이 있다.

  1. flex-grow 값은 0으로 설정된다. 그래서 리스트 아이템이 커지지 않는 이유다.
  2. 플렉스 아이템은 주축(main-axis)의 시작에 정렬된다 (기본 동작).
  3. 아이템이 주축(main-axis)의 시작 부분에 정렬되어 있기 때문에 오른쪽에 약간의 여유 공간이 남는다. 보이니?

presentation

이제 첫 번째 리스트 아이템(Branding)에 margin: auto를 추가하면 어떻게 되는지 확인하자.

li:nth-child(1) {
  margin-right: auto; /*applied only to the right*/
}

presentation

방금 무슨일이 일어났는가?

여분의 공간(extra space)이 첫 번째 플렉스 아이템의 오른쪽으로 이동 됐다.

presentation

이전에 다뤘던 내용을 기억하나?

플렉스 아이템에서 margin: auto를 사용하면, auto 값을 갖는 방향 (왼쪽, 오른쪽 또는 양쪽 모두)이 빈 공간을 차지하게 된다.

플렉스 아이템의 양쪽 모두에 auto margin을 한다면 어떻게 될까?

/*you may use the margin shorthand to set both sides if you wish*/
li:nth-child(1) {
  margin-left: auto;
  margin-right: auto;
}

presentation

이제 이 공간은 플렉스 아이템의 양쪽에 분산된다.

그렇다면 auto-margin을 사용 했을때 문제는 없을까?

한가지 문제가 있다. 주의를 기울이지 않으면 좌절의 원인이 될 수 있기 때문이다.

플렉스 아이템에서 auto-margin 정렬을 사용하면 justify-content 속성이 더 이상 작동하지 않는다.

예를 들어 justify-content 속성을 통해 위의 플렉스 컨테이너에 다른 맞춤 옵션을 설정해도 레이아웃에 아무런 영향을 미치지 않는다.

ul {
  justify-content: flex-end;
}

presentation

실제 사용 사례

네비게이션은 모든 웹사이트 또는 애플리케이션에서 매우 큰 부분을 차지한다. 모든 웹 사이트에는 일종의 네비게이션 시스템이 있다.

이 유명한 사이트가 어떻게 네비게이션을 구성했는지 살펴보자.

Flexbox를 통해 이러한 레이아웃을보다 효율적으로 구축하는 방법에 대해서 알고 있는가?

auto-margin 기능이 매우 편리하게 사용될 수 있는 곳을 자세히 살펴보자.

(i) Bootstrap Navigation

presentation

(ii) AirBnB desktop Navigation

presentation

(iii) Twitter desktop Navigation

presentation

실제로 코드를 작성해보는 것이 좋다.

네비게이션 시스템을 직접 구현해보자.

여기서 필요로하는 모든 내용은 이미 다 알고 있을 것이다.

다음 섹션에서 보자.

네비게이션 코딩 연습을 마친 후이기를 바라며 :-)

플렉스 방향(flex-direction)을 바꾸면 어떻게 될까?

경고: 이상한(weird) 현상을 볼 수 있음.

presentation

내가 플렉스 모델을 공부하기 시작했을 때, 이 부분이 가장 혼란스러웠다.

“플렉스 세상”에 많은 초보자들(newcomers) 역시 그럴거라고 생각한다.

기본적으로 주축(main-axis) 및 교차 축(cross-axis)은 “왼쪽에서 오른쪽”방향 “위에서 아래”방향으로 배치 된다고 얘기한 것을 기억하는가?

이전 섹션에서 설명한대로 이런 방향을 flex-direction: column을 사용해서 바꿀 수 있다.

flex-direction: column을 사용하면 아래 그림과 같이 주축과 교차축이 변경된다.

presentation

presentation

영어로 글을 작성한 적이 있다면 글이 왼쪽에서 오른쪽으로 그리고 위에서 아래로 작성되는 것을 이미 알고있는 것이다.

Flexbox의 기본 주축 및 교차축도 이와 동일한 방향으로 되어있다.

하지만 플렉스 방향(flex-direction)을 컬럼(column)으로 변경하면, 더이상 “영어”의 패턴이 아닌 일본어의 패턴을 사용하게 된다!

그래 맞다, 일본어.

일본어로 글을 작성해본적이 있다면 익숙 할 것이다. (나는 일본어로 글을 한 번도 써본적이 없다.)

일본어 텍스트는 전통적으로 위에서 아래로 쓰여진다!

이것이 왜 영어를 쓰는 사람들에겐 다소 혼란스러울 수 있는지 설명한다.

presentation

아래의 예를 살펴보자. 이번에는 flex-direction을 변경한 것을 제외하곤, 기본 3 개의 리스트 아이템이 있는 정렬되지 않은 리스트(ul)이다.

<ul>
  <li></li>
  <li></li>
  <li></li>
</ul>
ul {
  display: flex;
  flex-direction: column;
}

방향을 바꾸기 전의 모습은 다음과 같다.

presentation

방향을 변경 한 후.

presentation

정말 Flexbox로 해결 한다고?

presentation

많은 디자이너들이 CSS를 작성 할 때 직면하는 전형적인 문제들은 Flexbox로 간단히 해결되었다.

Philip Waltonsolved-by-flexbox 프로젝트에서 6 가지 전형적인 문제를 보여줬다 (이 글을 쓰는 시점에서).

이전에 CSS가 갖고 있는 제한 사항에 대해 광범위하게 논의하고 Flexbox가 제공하는 현재 솔루션에 대해 설명한다.

이 글을 다 읽은 후에 살펴 보기 바란다.

연습 섹션에서 Flexbox로 음악 앱 레이아웃을 작성하는 과정에서 위의 글에서 다루는 몇 가지 개념에 대해 설명하겠다.

호환되지 않는 브라우저를 위한 Flexbugs와 gotchas

github 저장소를 한 번 확인 해보자.

나보다 똑똑한 사람들이 Flexbox 버그 리스트와 이것을 해결 할 수 있는 방법에 대해서 정리한 저장소이다.

내가 예상 한대로 뭔가가 작동하지 않을 때 내가 제일 먼저 확인하는 곳이다.

다음 연습 섹션에서 몇 가지 중요한 버그를 통해 이에 대해 다룰 것이다.

Flexbox로 음악 앱 레이아웃 만들기

presentation

지루한 이론을 마쳤으니, 재미있는 프로젝트를 만들어 보자.

새로 습득한 Flexbox 기술을 적용 할 때이다.

어떤 프로젝트를 만들면 좋을까 하다 고양이를 위한 음악 앱 레이아웃을 만들어 보는게 좋을것 같다고 생각했다.

나는 이것을 Catty Music이라고 부르겠다.

완성 된 레이아웃은 다음과 같다. 완전히 Flexbox로 만들었다.

presentation

여기에서 온라인으로 볼 수 있다.

모바일에서 볼 경우 약간 다른 모습일 것이다. 이것에 대해서는 이 글의 반응형(responsive) 디자인 섹션에서 다룰 것이다.

Flexbox로 전체 레이아웃을 완성했는데, 사실 많은 사람들은 이것이 문제가 있다고 여긴다.

여러 가지 이유로 이렇게 하는 것은 이상적이지 않을 수 있다. 그러나 이 프로젝트에서는 의도적이었음을 밝힌다. Flexbox로 가능한 모든 작업을 단일 프로젝트 내에서 사용하는 것을 보여주기 위해서였다.

Flexbox 모델을 사용하는 것이 옳은지 아닌지에 대해 궁금한 점이 있다면 내 글을 참고 하자.

Flexbox is awesome but don’t use it here

Catty Music은 모두 Flexbox 모델을 사용하였다. Flexbox로 어떤것이 가능한지 보여주기위한 의도가 포함되어있다.

그럼 이제 시작해보자!

Catty Music 레이아웃을 만드는 계획을 세워보도록 하자.

어디서부터 시작해야 될까?

Flexbox로 레이아웃을 만들기전에 레이아웃의 어떤 부분이 플렉스 컨테이너(flex-containers)가 되어야 할지 생각해봐야 한다.

그런 다음 Flexbox의 강력한 정렬 속성을 활용할 수 있다.

분리(The Breakdown)

전체 컨테이너 바디를 플렉스 컨테이너 (아래 이미지의 빨간색 테두리에 포함)로 배치하고 레이아웃의 다른 섹션을 플렉스 아이템 (item 1과 2)으로 나눌 수 있다.

presentation

item 1에는 음악 컨트롤 버튼이 포함 된 섹션인 “푸터(footer)” 이외의 레이아웃의 모든 부분이 포함되어 있기 때문에 전적으로 이해가 되는 부분이다.

플렉스 아이템 역시 플렉스 컨테이너로 변경 할 수 있다는 것을 알고 있었는가?

그렇다, 가능하다!

원하는만큼 중첩시킬 수 있다 (합리적인 수준의 레벨을 유지하는 선안에서).

item 1 (첫 번째 플렉스 아이템)은 플렉스 컨테이너로 만들 수도 있다.

사이드바 (item 1b)와 메인 섹션 (item 1a)은 플렉스 아이템이 된다.

presentation

이렇게 레이아웃을 분리하면 정말 좋은 멘탈 모델(mental model)을 얻게 된다.

Flexbox 모델로 더욱 복잡한 레이아웃을 만들게 된다면 이것이 얼마나 중요한지 알 수 있다.

위의 이미지처럼 멋진 이미지는 필요 없다. 간단한 종이로 스케치 해보는 것 정도면 충분하다.

원하는만큼 중첩하여 플렉스 컨테이너를 선언 할 수 있다고 얘기한 것을 기억하는가? 여기에 한번더 중첩해서 사용해도 문제가 되지 않는다.

위의 주요 섹션 (item 1a)을 살펴보자.

또한 아래에 하이라이트된 섹션을 플렉스 컨테이너로 만들 수도 있다. ”item 1a - A” 및 ”item 1a - B

presentation

메인 섹션 (item 1a)에 플렉스 컨테이너를 만들지 않고 하이라이트된 섹션을 위해 두 개의 “div”를 넣을 수도 있다.

그렇다. ”item 1a-A“와 ”item 1a-B“가 수직으로 쌓여 있기 때문에 가능하다.

기본적으로 “divs”는 세로로 쌓인다. 박스 모델(box model)이 작동하는 방식이다.

메인 섹션을 플렉스 컨테이너로 만들면 강력한 정렬 속성을 사용 할 수 있다.

Flexbox의 ”flex“은 유연함(flexible)을 의미한다.

플렉스 컨테이너는 기본적으로 유연하고 일종의 반응형이다.

이것은 일반 “div” 대신 플렉스 컨테이너를 사용하는 또 다른 이유 일 수 있다. 시나리오에 따라 다르긴 하지만 말이다.

Katty Music을 만들면서 다른 것들도 간단히 다루도록 하겠다. 이제 몇 가지 코드를 작성해야한다.

기본 HTML 세팅

아래에 HTML부터 시작하자.

<!DOCTYPE html>
<html>
  <head>
    <title>Catty Music</title>
  </head>
  <body>
    <main></main>
    <!--to contain the main section of the app-->
    <footer></footer>
    <!--to contain the music control buttons and song details-->
  </body>
</html>

기본 스타일:

html,
body {
  height: 100%; /*setting this explicitly is important*/
}
body {
  display: flex; /*flex superpowers activated! */
  flex-direction: column; /*Stack the flex-items (main and footer elements) vertically NOT horizontally*/
}

Flexbox 모델을 사용하기위한 첫 번째 단계는 플렉스 컨테이너를 설정하는 것이다.

위의 코드와 정확히 같다. body 엘리먼트의 display 속성을 flex로 설정한다.

이제 body 엘리먼트가 플렉스 컨테이너가 됐다.

플렉스 아이템도 정의되어 있다 (item 1item 2) - 이전에 완료된.

이 개념이 여전히 이해가 되지 않는다면 초기 분리(initial breakdown) 단계에서 보여준 이미지를 다시 한 번 보는 것이 좋다.

푸터가 맨 아래에 고정되도록 한다

음악 컨트롤이있는 푸터는 페이지 하단에 붙어 있지만 메인 섹션은 나머지 공간을 채우도록 한다.

어떻게 해야할까?

main {
  flex: 1 0 auto; /*fill the available space*/
}
footer {
  flex: 0 0 90px; /*don't grow or shrink - just stay at a height of 90px.*/
}

위 코드의 주석을 참조하자.

메인 섹션의 전체 공간을 채우는 것은 flex-grow 속성을 사용하면 상대적으로 쉽다.

flex-grow 값을 1로 설정하면된다. flex-shrink 속성도 0으로 설정해야한다. 왜?

flex-direction이 변경 되었기 때문에 그 이유가 분명하지 않을 수 있다.

일부 브라우저에는 플렉스 아이템이 컨텐츠 크기보다 줄어드는 버그가 있다.

이 버그의 해결 방법은 기본값인 1이 아니라 flex-shrink 값을 0으로 유지하고 flex-basis 속성을 auto로 설정하는 것이다.

이렇게 말하는 것이다: ”플렉스 아이템의 크기를 자동으로 계산하되, 절대 줄어들게 하지 마시오.

이 값을 사용해도 여전히 플렉스 아이템의 기본 동작을 유지한다.

플렉스 아이템은 브라우저의 사이즈를 줄이면 축소되는데, 크기 조정은 shrink 속성을 기반으로하지 않는다. 대신, 플렉스 아이템의 폭을 자동으로 다시 계산하는 것을 기반으로 한다. flex-basis: auto

이렇게하면 플렉스 아이템의 크기가 이것의 폭 또는 높이 (선언 된 경우)만큼 커지게 하거나 기본 컨텐츠 크기만큼 커지게 한다.

flex-shorthand 속성을 잊지 말자. 더 많은 shorthand에 대해서 다룰 것이다.

간격 및 색상을 정의하기 위해 약간의 스타일을 적용해보자.

body {
  display: flex;
  flex-direction: column;
  background-color: #fff;
  margin: 0;
  font-family: Lato, sans-serif;
  color: #222;
  font-size: 0.9em;
}
footer {
  flex: 0 0 90px;
  padding: 10px;
  color: #fff;
  background-color: rgba(61, 100, 158, 0.9);
}

아래와 같을 것이다.

presentation

어떻게 변경되는지를 보면, 훨씬 나아질 것이다.

사이드바 수정.

HTML을 수정하자.

<main>
  <aside>
    <!--This represents the sidebar and contained in it are icon sets from font-awesome-->
    <i class="fa fa-bars"></i>
    <i class="fa fa-home"></i>
    <i class="fa fa-search"></i>
    <i class="fa fa-volume-up"></i>
    <i class="fa fa-user"></i>
    <i class="fa fa-spotify"></i>
    <i class="fa fa-cog"></i>
    <i class="fa fa-soundcloud"></i>
  </aside>
  <section class="content">
    <!--This section will house everything other than the sidebar-->
  </section>
</main>

소스만 확인해도 많은 것을 설명해준다.

아이콘의 경우 인기있는 Font Awesome 라이브러리를 사용하고 있다.

아이콘을 추가하는 것은 CSS 클래스를 추가하는 것만큼 간단하다.

앞에서 설명한 것처럼, 위의 ”main“섹션은 플렉스 컨테이너가 된다. 사이드바 (aside 태그로 표시) 및 섹션은 플렉스 아이템이다.

main {
  flex: 1 0 auto; /*Is a flex item*/
  display: flex; /*I just included this! - now a flex container with flex items: sidebar & main content section*/
}

점점 흥미로워지는가?

메인 섹션은 플렉스 컨테이너가 됐다. 플렉스 아이템 중 하나인 사이드바를 다뤄보자.

푸터를 페이지 아래쪽에 고정 한 것처럼 페이지의 왼쪽에도 사이드바를 고정 할 것이다.

aside {
  flex: 0 0 40px; /*do not grow or shrink. Stay fixed at 40px*/
}

사이드바에 아이콘이 수직으로 쌓여 있어야한다.

사이드바를 플렉스 컨테이너로 만들고 모든 아이콘을 수직으로 쌓을 수있는 flex-direction을 지정할 수 있다.

그런 다음 정렬 속성을 적용하여 아이콘을 배치한다.

아래에서 방법을 확인하자.

aside {
  /* ...  */
  display: flex; /*Now a flex-container too*/
  flex-direction: column; /*stack icons vertically*/
  /*since direction is changed, this works on the vertical direction*/
  justify-content: space-around;
  align-items: center; /*direction is changed! This affects the horizontal direction. Places Icons in the center*/
  background-color: #f2f2f2; /*make me pretty*/
}
aside i.fa {
  font-size: 0.9em; /*font size for the icons*/
}

자세하게 주석을 달았으니 주석을 참조하자.

지저분한 CSS 핵(hack)을 사용하지 않고, 몇 라인의 코드를 추가함으로써 합리적인 코드로 구성이 됐다.

presentation

메인 컨텐츠 섹션은 현재 비어 있다.

이제 메인 섹션을 채워보자.

메인 섹션에 컨텐츠 추가.

완성된 프로젝트를 다시 한 번 살펴 보는게 도움이 될 것이다. 얼마만큼 프로젝트가 진행 되고 있는지 짐작 할 수 있기 때문이다.

더 중요한 점은 다음에 어떤 것을 다룰지 예상하는데 도움이 된다는 것이다.

HTML을 수정하고 .content 섹션 안에 집어 넣자.

<section class="content">
  <!--This section was empty. Populating it with content-->
  <div class="music-head">
    <!--First list item: contains music details-->
    <img src="images/cattyboard.jpg" />
    <!--Album art-->
    <section class="catty-music">
      <!--other details of the album-->
      <div>
        <p>CattyBoard Top 100 Single Charts (11.06.36)</p>
        <p>Unknown Artist</p>
        <p>2016 . Charts . 100 songs</p>
      </div>
      <div>
        <!--Music controls-->
        <i class="fa fa-play"> &nbsp;Play all</i>
        <i class="fa fa-plus"> &nbsp;Add to</i>
        <i class="fa fa-ellipsis-h">&nbsp;&nbsp;More</i>
      </div>
    </section>
  </div>
  <!--end .music-head-->
  <!--Second list item: Contains a list of all songs displayed-->
  <ul class="music-list">
    <li>
      <p>1. One Dance</p>
      <p>Crake feat CatKid &amp; Cyla</p>
      <p>2:54</p>
      <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p>
    </li>
    <li>
      <p>2. Panda</p>
      <p>Cattee</p>
      <p>4:06</p>
      <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p>
    </li>
    <li>
      <p>3. Can't Stop the Feeling!</p>
      <p>Catin Cimberlake</p>
      <p>3:56</p>
      <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p>
    </li>
    <li>
      <p>4. Work From Home</p>
      <p>Cat Harmony feat Colla</p>
      <p>3:34</p>
      <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p>
    </li>
  </ul>
</section>

코드가 길어 보이지만 간단한 코드이다.

나는 비어있는 컨텐츠 섹션에 앨범 아트와 Catty 앨범의 일부 세부 사항을 담고있는 div를 넣었다.

ul은 앨범에서 노래 목록을 포함하고 있다.

노래 제목, 아티스트, 시간 및 ”catty cloud sync“는 목록 내의 개별 단락에 포함된다.

그럼 어떻게 스타일을 추가해야 할까?

먼저, .content 섹션을 플렉스 컨테이너로 만들어야한다.

.content {
  display: flex;
  flex: 1 1 auto; /*this makes sure the section grows to fill the entire available space and shrinks too*/
  flex-direction: column;
}

플렉스 아이템 역시 다루어야 한다.

.music-head {
  flex: 0 0 280px; /*Same memo, don't grow or shrink - stay at 280px*/
  display: flex;
  padding: 40px;
  background-color: #4e4e4e;
}
.music-list {
  flex: 1 0 auto;
  list-style-type: none;
  padding: 5px 10px 0px;
}

.music-head는 앨범 아트 및 기타 관련 앨범 세부 정보를 포함하고 있다.

확대(grow)하거나 축소(shrink)되지 않도록 height는 280px로 고정한다.

이미 부모 엘리먼트의 flex-direction이 바뀌어 있기 때문에 width가 아닌 height를 고정하는 것이다.

아 그리고 나중에 플렉스 컨테이너가 필요하기 때문에 display: flex를 추가한다.

.music-list는 노래 목록을 가지고 있으며 위의 .music-head와 공유되도 남은 가능한 공간을 채운다.

이것은 아직 예쁘진 않지만 계속 따라오고 있다면 잘하고 있는 것이다.

presentation

여기에 몇 가지 문제가 있다.

\1. 노래 목록은 끔찍해 보인다.

presentation

\2. 뮤직 아트가 포함된 섹션에는 정말 보기 흉한 텍스트가 있다.

presentation

다시 말하지만, 이러한 문제들을 해결할 수 있도록 여러분을 안내 할 것이다.

아래에 해결책이 있다.

노래 목록 다루기

각 노래 목록에는 4 개의 단락이 있다. 노래 제목, 아티스트, 재생 시간 및 ”catty cloud sync“.

이 모든 것을 한 줄에 넣고 각 단락이 같은 공간을 차지할 수 있는 방법이 있어야한다.

Flexbox를 이용하자!

여기의 개념은 많은 그리드 시스템에서 사용되는 것과 동일하다.

그것을 코드로 변환하자.

li {
  display: flex; /*Paragraphs are now displayed on one line*/
  padding: 0 20px; /*Some breahing space*/
  min-height: 50px;
}
li p {
  flex: 0 0 25%; /*This is the sweet sauce*/
}

여기서 무슨 일이 일어나고 있는지 보이는가?

flex: 0 0 25%;

“확장(grow), 축소(shrink)하지 말고 각 단락은 공간의 25%를 채워야 한다”.

공백은 단락간에 동일하게 공유된다.

이 테크닉 사용하기

이 테크닉은 매우 중요하다. 이를 사용하여 서로 다른 컨텐츠 영역을 만들 수 있다.

예를들어, 한 섹션은 사용 가능한 공간의 60%를 채우고, 다른 섹션은 공간의 40%를 채우게 할 수 있다.

.first-section: 0 0 60%;
.second-section: 0 0 40%;

그리드 시스템을 만드는 데 이 테크닉을 사용할 수 있다.

목록은 이제 아래처럼 보일 것이다.

presentation

목록에 색상을 번갈아 표시하고 ”catty cloud sync“레이블도 처리하자.

li span.catty-cloud {
  border: 1px solid black;
  font-size: 0.6em;
  padding: 3px;
}
li:nth-child(2n) {
  background-color: #f2f2f2;
}

이제 정말로 Flexbox 용어에 대해 더 잘 이하하게 될 것이다.

이것은 당신이 지금 해야만 하는 것이다.

presentation

두 번째 문제를 지금 다룰 것이다.

앨범 세부 정보 텍스트를 더 예쁘게 보이도록.

정말 간단한 것들을 다룰 것이다.

.catty-music {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  font-weight: 300;
  color: #fff;
  padding-left: 50px;
}
.catty-music div:nth-child(1) {
  margin-bottom: auto;
}
.catty-music div:nth-child(2) {
  margin-top: 0;
}
.catty-music div:nth-child(2) i.fa {
  font-size: 0.9em;
  padding: 0 0.7em;
  font-weight: 300;
}
.catty-music div:nth-child(1) p:first-child {
  font-size: 1.8em;
  margin: 0 0 10px;
}
.catty-music div:nth-child(1) p:not(:first-child) {
  font-size: 0.9em;
  margin: 2px 0;
}

거의 끝났다.

presentation

간단한 연습

나는 당신이 연습 해볼 수 있도록 푸터를 남겨뒀다.

푸터를 직접 고쳐보자. 위에서 사용한 같은 테크닉을 사용하자.

막힌다면 Catty Music의 전체 소스 코드를 언제든지 확인할 수 있다.

전체 푸터를 플렉스 아이템으로 나눌 수도 있다.

presentation

와우. 나는 당신이 여기까지 왔다는 것을 믿을 수 없다. 멋지다! 이제 Flexbox 닌자가되고 있다.

다음으로, Flexbox가 반응형 디자인에 어떻게 도움이되는지 살펴 보겠다.

Flexbox를 이용한 반응형 디자인

presentation

이 글은 Flexbox 모델에 중점을 두었으므로 반응형 디자인에 대해서는 깊이 다루지는 않을 것이다.

앞서 말했듯이, 우리는 Flexbox 모델을 통해 이미 어느정도 반응형 디자인을 얻었다.

Flexbox는 “유연한 상자(flexible box)“와 같다.

그러나 미디어쿼리를 통해 다양한 화면 크기를 타겟팅 한 다음 플렉스 동작을 변경할 수 있다.

다음은 그 예제이다.

정렬되지 않은 목록을 다시 사용하자.

<ul>
  <li>Home</li>
  <li>About</li>
  <li>Contact</li>
  <li>Register</li>
  <li>Login</li>
</ul>

그리고 약간의 스타일 추가…

ul {
  list-style-type: none;
  display: flex;
  border: 1px solid #4e4e4e;
}
li {
  flex: 0 0 auto;
  padding: 10px;
  margin: 10px;
  background-color: #8cacea;
  color: #fff;
  font-size: 1em;
}

당신은 이제 플렉스 전문가이다. 그래서 당신은 무슨 일이 일어나고 있는지 이해 할 것이다.

네비게이션 바 모양은 다음과 같다.

presentation

데스크탑 및 태블릿의 경우 멋지지만 특정 화면 크기에서는 이상해 보인다.

모바일에서는 네비게이션 아이템을 세로로 쌓아 올릴 수 있다.

미디어쿼리를 사용하면 된다.

@media screen and (max-width: 769px) {
  /* code here only applies to screen devices that have a width lesser than 769px*/
  ul {
    flex-direction: column; /* On smaller devices, switch the direction*/
  }
}

presentation

반응형 디자인에 대해 어느정도 지식이 있다면 많이 도움이 된다.

Flexbox 모델을 기존 지식으로 바꾸기만 하면 된다.

그건 그렇고, 나는 당신이 미디어쿼리가 무엇인지 이해한다고 가정을 했는데, 만약 미디어쿼리에 대해 잘 모른다면 아래의 간단한 요약을 참고하자.

미디어쿼리(Media Queries)

미디어쿼리는 반응형 디자인의 핵심이다. 이 도구를 사용하여 특정 화면 크기에서 실행할 코드를 지정 할 수 있다.

미디어쿼리가 사용되는 가장 보편적인 형식은 @media 룰이다.

이것은 다음과 같다:

@media screen and (max-width: 300px) {
  /*write your css in this code block*/
}

소스만 봐도 거의 이해 할 수 있을 것이다.

“최대 너비 300px의 화면 디바이스의 경우 이 작업을 수행”

코드 블록 내의 모든 스타일은 ”screen and (max-width: 300px)“과 일치하는 디바이스에만 적용된다.

이것으로 약간의 혼란을 해결하는데 도움이되었으리라 생각한다.

간단한 연습

Catty Music은 모바일 디바이스에서 다르게 보인다. 그것은 좋은 소식이다. 더 나은 점은 이것을 다시 만들어야한다는 것이다.

presentation

문제가 발생하는 경우 이 튜토리얼의 저장소 링크는 다음 섹션에 있다. 이것에 대한 해결책 또한 repo에 있다.

이제 거의 끝나간다!

결론 섹션에서는 브라우저 지원, 유용한 링크 및 리소스에 대해 설명하겠다.

결론

presentation

플렉스 컨테이너 및 플렉스 아이템 정렬 속성을 사용하는 방법을 배웠다.

절대적(absolute) 및 상대적(relative) 플렉스, auto-margin 정렬 및 flex-direction 전환에 대해 설명했다.

Catty Music을 제작할 때 “플렉스 스킬(flex skills)“을 적용 할 수 있는 기회를 얻었다. 그런 다음 반응형 디자인에 대해서도 언급했다.

정말로 긴 여정이었다.

이제 최종 개념을 설명하겠다. 리소스와 링크를 통해 도움을 받길 바란다.

브라우저의 Flexbox 지원 범위는 어떨까?

프로덕션 환경에서 Flexbox 모델을 사용할 때 자주 묻는 질문이다.

나는 그 질문에 완벽하게 대답 할 수는 없지만, canisuse 웹 사이트에서 확인 할 수 있다.

브라우저 지원은 아주 인상적이다. 여기서 직접 볼 수 있다.

presentation

처음에 이 사이트를 여러 번 보았지만 데이터가 의미하는 바를 파악할 수 없었다. 여기에 간단한 설명이 있다.

caniuse 웹사이트의 오른쪽 하단에는 legend가 있다.

presentation

위의 이미지를 보거나 사이트를 방문하여 legend를 찾아 볼 수 있다.

추가 리소스

도움이 되기를 바란다.

  1. PDF document
  2. Play with the Catty Music code online
  3. The Repo for the entire “Understanding Flexbox” tutorial
  4. Mastering Modern CSS layouts Book
  5. Flexbox Playground and Code Generator
  6. Flexbox Froggy: A Cool Flexbox Game

마지막으로, 여기까지 따라와 줘서 고맙다.

Call to Action

Flexbox와 CSS Grid를 처음부터 마스터하는 것을 도와줄 수 있다. 여기에 연락처를 남겨 준다면 기꺼이 돕겠다. Flexbox Cheatsheet 가이드를 무료 선물로 보내준다. 여기서 가입하면 된다.

presentation

이 글은 Ohans Emmanuel의 Understanding Flexbox: Everything you need to know_을 번역한 글 입니다.