가변상자

가변상자는 행과 열 형태로 항목 무리를 배치하는 일차원 조판 메서드입니다. 항목은 부족한 공간에 맞추기 위해 축소되거나 여분의 공간을 채우기 위해 변형된다. 이 문서는 근간이 되는 내용 전체를 설명합니다.

선결 사항: 에이치티엠엘의 기초 (에이치티엠엘 입문서)와 씨에스에스 작동 방식에 대한 개념(씨에스에스 입문서를 공부하세요.)
목표: 웹 조판을 생성하기 위해 가변상자 조판 시스템을 사용하는 방법을 학습하기.

왜 가변상자인가?

오랫동안 씨에스에스 조판을 작성할 수 있는 신뢰할 수 있는 크로스 브라우저 호환 도구는 부동체위치잡기 도구였습니다. 이것들은 무난하고 작동하지만, 어떤 면에서는 되려 제한적이고 좌절감을 맞보게 합니다.

다음과 같은 간단한 조판 요구 사항은 그러한 도구를 사용하여 달성하기가 어렵거나 불가능합니다. 또한, 편리하지도 유연한 방식도 못됩니다.

  • 부모 요소 내부에 포함된 블록 콘텐츠를 세로로 중심부에 맞추기.
  • 사용 가능한 너비와 높이에 관계없이 하나의 컨테이너에 포함된 모든 자녀 요소가 주어진 너비와 높이를 똑같은 크기로 점유하기.
  • 다단 조판에 포함된 모든 단이 서로 다른 크기의 콘텐츠를 포함하고 있더라도 동일한 높이로 채택하기.

다음 섹션에서 확인하겠지만, 가변상자는 많은 조판 작업을 훨씬 쉽게 만들어 줍니다. 본격적으로 파헤쳐봅시다!

간단한 예제 소개

이 문서에서 우리는 여러분이 가변상자의 작동 방식을 이해하는데 도움이 되는 일련의 연습을 수행하도록 하겠습니다. 시작하려면, 첫 번째 착수 파일인 flexbox0.html을 우리의 깃허브 저장소에서 사본을 내려받기하여 최신 브라우저(Firefox 또는 Chrome 등)에서 동 파일을 열어 코드 편집기에서 코드를 살펴봐야 합니다. 당신은 그걸 시연한 실제 장면을 여기서도 볼 수 있습니다.

(편집기로 본) 소스안에 최상위 수준에 <header> 요소와 세 개의 <article>를 포함한 <section> 요소가 있음을 알 수 있습니다. 우리는 이것들을 사용해 상당히 표준적인 삼단 조판을 생성할 겁니다.

가변상자로 조판할 요소 지정

먼저 어떤 요소들을 가변상자로 조판할 요소를 선택해야 합니다. 이를 위해 영향을 주고 싶은 요소의 부모 요소에 특별한 display 속성값을 지정합니다. 이 경우 우리는 <article> 요소를 조판하길 원하므로 (가변 컨테이너가 될) <section>에 해당 속성값을 지정합니다:

section {
  display: flex;
}

그 결과는 다음과 같아야 합니다:

자. 이 단일 선언이 우리에게 필요한 모든 것을 제공합니다. 놀랍죠, 그쵸? 우리는 단의 크기가 동일한 다단 조판를 갖게 되었고, 단의 높이가 모두 같습니다. 이렇게 된 까닭은 (가변 컨테이너의 자식인) 가변 항목에 주어진 기본값이 이와 같은 일반적인 문제를 해결하도록 설정되었기 때문입니다. 관련 내용은 나중에 추가합니다.

참고: 인라인 항목을 가변상자로 취급해 조판하길 희망한다면 display 속성값을 inline-flex로 지정할 수도 있습니다.

가변 모델의 측방

요소들을 가변상자로 조판될 때 그 상자들은 두 개의 축을 따라 배치됩니다.

flex_terms.png

  • 기본 축 (main axis) 은 가변 항목이 배치되고 있는 방향으로 진행하는 축입니다(예: 페이지를 가로지르는 행 또는 페이지 밑으로 쌓이는 열). 이 기본 축의 시작과 끝을 일컬어 main startmain end라고 합니다.
  • 교차축 (cross axis) 은 가변 항목이 내부에 배치되는 방향에 직각을 이루는 축입니다. 이 축의 시작과 끝을 일컬어 cross startcross end라고 합니다.
  • display: flex이 설정된 부모 요소(우리 예제에서 <section>이 해당)를 일컬어 가변 컨테이너 (flex container) 라고 합니다.
  • 가변 컨테이너 내부에 가변 상자로 조판되는 항목을 일컬어 가변 항목 (flex items) 이라고 합니다(우리 예제에서 <article> 요소가 해당됩니다).

후속 절을 진행할 때 이러한 용어를 명심하길 바랍니다. 사용 중인 어떤 용어에 대해 혼란스러워지면 언제든지 다시 참조할 수 있습니다.

행 또는 열?

가변상자는 기본 축이 진행되는 방향(자식 가변상자들이 컨테이너 내부에 배치되는 방향)을 지정하는 flex-direction 속성을 제공합니다. 기본값으로 이것은 row로 설정되어 브라우저의 기본 언어가 작동하는 방향(영어 브라우저의 경우 왼쪽에서 오른쪽)을 따라 일렬로 배치됩니다.

다음 선언문을 <section> 규칙에 추가하세요:

flex-direction: column;

이로써 항목 무리를 열 조판으로 되돌려 놓는걸 확인하게 된다. 해당 항목들은 어떤 내용의 씨에스에스를 추가하기 이전 상황과 유사하다. 진도를 더 나가기 전에 동 선언문을 예제에서 삭제하십시오.

참고: 당신은 row-reversecolumn-reverse 속성값을 사용하여 역방향으로 배치할 수 있습니다. 이들 값으로도 실험해보십시요!

접기

당신의 조판에 너비 또는 높이가 고정 크기를 갖고 있어 생기는 한 가지 문제는 결국 가변상자 자식 요소가 컨테이너에서 대열이탈하면서 조판이 깨진다는 것입니다. 우리가 제시하는 flexbox-wrap0.html 예제를 확인하고 난 뒤 라이브 보기를 시도하세요(이 예제를 따라해보고 싶다면 이제 이 파일의 사본을 내려받으세요):

여기서 우리는 자식들이 정말로 소속 컨테이너에서 이탈하는 모습을 확인할 수 있습니다. 이것을 해소할 수 있는 한 가지 방법은 다음 선언을 <section> 규칙 부분에 추가하면 됩니다:

flex-wrap: wrap;

또한, 디음 선언문을 <article> 규칙 부분에 추가해보세요:

flex: 200px;

지금 시도해보십시오. 동 규칙이 포함된 상태에선 조판 모양이 개선되는 걸 보게 됩겁니다:

우리는 이제 여러 행을 갖게 되었다. 많은 가변상자 자녀들이 합당하다 싶게 각 행마다 (분배되어) 알맞게 맞춰졌습니다. 대열이탈된 것들은 다음 행으로 넘어갑니다. 아티클 요소에 flex: 200px 선언이 지정되었다는 의미는 각 요소에 적어도 200px 너비가 지정되었다는 의미이다. 우리는 나중에 이 속성에 대해 더 자세히 논의할 겁니다. 마지막 행에 있는 마지막 몇몇 자식들의 각 너비가 더 연장되면서 전체 행이 마찬가지로 채워진 것을 볼 수 있습니다.

하지만 할 수 있는 게 더 있습니다. 우선, flex-direction 속성값을 row-reverse로 변경해 보십시오. 이제 여러 행 조판을 보유한 것은 마찬가지지만, 브라우저 창의 반대쪽 구석에서 시작하여 역방향 대열이 된 것이 확인될 겁니다.

가변 대열 약칭

이 시점에서 flex-directionflex-wrapflex-flow를 대신하는 약칭이 존재한다는 점을 언급할 가치가 있다. 예를 들어, 여러분은 다음을

flex-direction: row;
flex-wrap: wrap;

다음으로 대체할 수 있다.

flex-flow: row wrap;

가변 항목의 가변 크기 조정

이제 첫 번째 예제로 복귀해서, 우리가 어떻게 가변 항목의 비율을 조절할 수 있는지 살펴봅시다. flexbox0.html사본을 브라우저 탭으로 열거나 flexbox1.html 사본을 새로운 출발점으로 삼으세요.(라이브 참조).

첫째, 당신의 씨에스에스 파일 하단에 다음 규칙을 추가하십시오:

article {
  flex: 1;
}

이것은 각 가변 항목이 기본 축을 따라 남은 공간을 어느 정도나 점유할지를 결정하는 단위가 없는 비율 값입니다. 이 경우, 우리는 각각의 <article> 요소에 1의 값을 부여하고 있는데, 이는 패딩과 여백이 지정된 이후 남은 여분의 공간을 모두 동등한 크기로 점유하게 된다는 의미입니다. 그것은 비율이며, 각 가변 항목에 400000의 값을 부여하면 정확히 동일한 효과가 있음을 의미합니다.

이제 이전 규칙 아래에 다음 규칙을 추가합시다.

article:nth-of-type(3) {
  flex: 2;
}

이제 새로 고침할 때, 세 번째 <article>이 다른 두 개보다 사용 가능한 너비의 두 배나 많이 점유한다는 것을 알 수 있습니다. 말하자면 현재 총 4개의 비례 단위가 있는 겁니다. 처음 두 개의 가변 항목은 각각 하나로 구분되어 사용 가능한 공간의 1/4을 차지합니다. 세 번째 것은 두 개의 단위(2배율)를 차지하기 때문에 사용 가능한 공간의 2/4를 점유합니다(또는 1/2).

또한 가변 값 내에서 최소 크기 값을 지정할 수 있습니다. 다음과 같이 문서 부분의 기존 규칙을 업데이트해 보십시오.

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}

이것은 기본적으로 "각 가변 항목은 먼저 사용 가능한 공간에서 200px를 부여받습니다. 그 후, 나머지 사용 가능한 공간은 비례 단위에 따라 분배됩니다." 새로 고침을 해보면 공간 배분 방식이 달라진 것이 확인될 겁니다.

가변 상자의 실제 값은 가변성/반응성에 포함되어 있다고 볼 수 있습니다. 다시말해 브라우저 창의 크기를 재조정하거나 다른 <article> 요소를 추가하더라도 조판이 계속 정상적으로 작동합니다.

가변: 약칭 對 정식 명칭

flex 최대 세 가지 서로 다른 값을 지정할 수 있는 약칭 속성입니다.

  • 단위없는 비례 값은 우리가 위에서 논의한 바 있습니다. 단위없는 비례 값은 flex-grow라는 정식 명칭 속성을 사용하여 개별적으로 지정할 수 있습니다.
  • 두 번째 단위없는 비례 값인 flex-shrink는 가변 항목이 컨테이너에서 넘칠때(대열이탈) 존재를 드러냅니다. 이 값은 컨테이너 대열이탈을 방지하기 위해 넘치는 양을 각 가변 항목의 크기에서 어느 정도나 뺏어올지를 지정합니다. 이 값은 꽤 고수준의 가변상자 기능이며, 우리는 이 문서에서는 추가 내용을 다루지 않겠습니다.
  • 위에서 논의했던 최소 크기 값입니다. 최소 크기 값은 flex-basis라는 정식 명칭 값을 사용하여 개별적으로 지정될 수 있습니다.

우리는 꼭 사용해야 할 경우가 아니라면(예를 들어, 이전 설정을 재정의하는 등) 가변 속성에 정식 명칭을 사용하지 말라고 권고합니다. 정식 명칭의 사용은 추가 코드 작성이 많아 질뿐만 아니라 다소 혼란스러울 수도 있습니다.

수평 및 수직 정렬

또한 가변상자 기능을 사용하여 기본 축 또는 교차축을 따라 가변 항목을 정렬할수 있습니다. 이 기능은 새로운 예제인 flex-align0.html을 통해 살펴보자(라이브로도 보세요). 가변 상자가 우리는 깔끔한 가변형 단추/툴바로 바뀌게될 겁니다. 지금 당장은 몇몇 단추들이 왼쪽 상단 모서리에 몰린 상태의 수평 메뉴 표시줄이 보입니다.

우선 이 예제의 사본을 취득합니다.

이제 예제의 씨에스에스의 맨 아래에 다음 내용을 추가하세요:

div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}

페이지를 새로 고치면 단추가 수평 및 수직으로 중심이 잘 맞춰져 있음을 알 수 있습니다. 우리는 두 가지 새로운 속성을 통해 이 작업을 수행했습니다.

align-items 속성은 가변 항목이 교차축 어디에 놓일 지를 제어합니다.

  • 이 속성값은 기본값으로 stretch입니다. 이 값은 교차축 방향으로 부모 요소를 채우기 위해 모든 가변 항목을 연장합니다. 부모가 교차 축 방향으로 고정폭이 주어지지 않았다면 모든 가변 항목이 최장 항목만큼 길어집니다. 이런 방식으로 우리의 첫 번째 예제가 기본값으로 같은 높이의 열을 얻게 된 것입니다.
  • 우리가 위의 코드에서 사용한 center 값은 항목 무리가 자기들 고유의 면적를 유지하는 동시에 교차축을 따라 중심에 놓이게 만듭니다. 그런 까닭에 현재 예제 속 단추가 수직으로 중심에 놓여있습니다.
  • 또한 교차축의 시작과 끝에 맞춰 모든 항목을 정렬하게 해주는 flex-startflex-end와 같은 값도 가질 수 있습니다. 자세한 내용은 align-items을 참조하십시오.

align-self 속성을 단추에 적용함으로써 가변 항목에 속한 개별 항목에 대한 align-items동작을 재지정할 수 있습니다. 예를 들어 다음을 씨에스에스에 추가해보세요:

button:first-child {
  align-self: flex-end;
}

이것이 어떤 효과를 미치는지 한번 보고, 다 보았다면 다시 제거하세요.

justify-content는 가변 항목 무리가 기본 축 상 어디에 놓이는지를 제어합니다.

  • 기본값은 flex-start이며, 이는 모든 항목이 기본 축의 시작 부분에 놓이도록 만듭니다.
  • 당신은 flex-end를 사용하여 항목 무리를 기본 축의 가장자리에 놓이도록 만들 수도 있습니다.
  • centerjustify-content를 대체할 수 있는 값으로 가변 항목 무리를 기본 축의 중심에 놓이도록 만들겁니다.
  • 우리가 위에서 사용했던 값인 space-around는 유용합니다. 모든 항목을 기본 축을 따라 고르게 분배하고 양쪽 끝에 약간의 공간도 남겨 놓습니다.
  • 그 외에도 space-between이라는 값도 있습니다. 이는 space-around와 매우 흡사하다. 다만 이것은 양쪽 끝에 공간을 남기지 않습니다.

우리는 진도를 더 나가기 전에 여러분이 이들 값을 가지고 어떻게 작동하는지 시험해보라고 권장하고 싶습니다.

가변 항목 무리의 순서

가변 상자에는 소스 순서에 영향을 미치지 않고 가변 항목의 조판 순서를 변경하는 기능도 있습니다. 이는 전통적인 조판 메서드로는 불가능했던 내용입니다.

이를 위한 코드는 간단합니다: 당신의 단추표시줄 예제 코도에 다음과 같은 씨에스에스를 추가해 보십시요:

button:first-child {
  order: 1;
}

페이지를 새로 고치면 이제 "스마일" 단추가 기본 축의 끝으로 이동한 것이 확인될 겁니다. 어떻게 이런 식으로 작동하는지 좀 더 상세히 얘기해 보겠습니다:

  • 기본값으로 모든 가변 항목들은 order 값이 0입니다.
  • 순위값이 높은 가변 항목들은 디스플레이 순서상 순위값이 낮은 항목들보다 나중에 나타납니다.
  • 순위값이 동일한 항목들은 소스 순서대로 나타납니다. 따라서 4개 항목의 순서값이 각기 2, 1, 1, 0로 설정된 경우 표시 순서는 제4, 제2, 제3, 제1 순이 됩니다.
  • 제 3항목은 동일한 순서값을 가지고 있지만, 소스 순서 상 제 2항목 뒤에 있기 때문에 제 2 항목 뒤에 나타납니다.

당신은 0 지정 항목보다 일찍 항목을 표시하도록 음수 순서 값을 설정할 수 있습니다. 예를 들어, 다음 규칙을 사용하여 "Blush" 단추를 기본 축의 시작 부분에 표시할 수 있습니다:

button:last-child {
  order: -1;
}

중첩된 가변 상자 무리

가변 상자를 사용하여 꽤 복잡한 조판을 만들 수 있습니다. 가변 항목을 가변 컨테이너로 설정해도 전혀 문제없습니다. 그렇게 되면 그 컨테이너의 자녀가 가변 상자처럼 배치됩니다. complex-flexbox.html를 찾아보세요. (라이브로도 보세요).

이를 위한 HTML은 상당히 간단합니다. 세 개의 <article>를 포함하는 <section> 요소가 있습니다. 세 번째 <article>은 세 개의 <div>를 포함하고 있습니다. :

section - article
          article
          article - div - button   
                    div   button
                    div   button
                          button
                          button

당 조판에 사용했던 코드를 살펴봅시다.

먼저 <section>의 자식들을 가변 상자로 취급해 배치하였습니다.

section {
  display: flex;
}

다음으로 <article> 무리 자체에 대해 약간의 가변 값을 설정하였습니다. 여기서 두 번째 규칙에 주목하십시오. 우리는 세 번째 <article>이 자기 자식들을 가변 항목처럼 배치하도록 설정하고 있습니다. 그러나 이번에는 열처럼 배치하고 있습니다.

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}

다음으로 첫 번째 <div>를 선택합니다. 우리는 먼저 선택된 요소에 100px의 최소 높이를 효과적으로 주기 위해 flex:1 100px;을 사용합니다. 그리고 나서 우리는 그것의 자식들을 (<button> 요소 무리를) 가변 항목처럼 배치하도록 설정했습니다. 여기서 우리는 그것들을 줄 바꿈 행에 배치하고, 우리가 앞서 본 개별 단추 예제에서 했던 것처럼 사용 가능한 공간의 중심에 정렬합니다.

article:nth-of-type(3) div:first-child {
  flex:1 100px;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-around;
}

마지막으로, 우리는 단추에 약간의 크기를 설정하되, 다소 흥미롭게도 1 auto라는 가변 값을 부여합니다. 이것은 매우 흥미로운 효과를 지니게 되는데, 브라우저 창의 폭을 조정해 보면 확인됩니다. 단추는 최대한의 공간을 점유할 뿐만아니라 동일 선상에 가능한 한 많은 요소를 놓으려고 합니다. 그러나 해당 요소들이 더 이상 동일 선상에 안착할 수 없을 경우 새로운 라인으로 밀려납니다.

button {
  flex: 1 auto;
  margin: 5px;
  font-size: 18px;
  line-height: 1.5;
}

크로스 브라우저 호환성

가변상자 지원은 파이어폭스, 크롬, 오페라, 마이크로소프트 에지 및 인터넷 익스플로러 11, 안드로이드 및 iOS 최신 버전 등 대부분의 신형 브라우저에서 사용할 수 있습니다. 그러나 가변상자를 지원하지 않는 (또는 지원하지만, 실제로 구식 버전의 가변상자를 지원하는) 구형 브라우저 사용자가 여전히 존재한다는 것을 알아야 합니다.

여러분이 단지 기술을 익히고 실험할 뿐이라면 호환성 문제는 그다지 중요하지 않습니다; 그러나 만약 여러분이 실제 웹사이트에서 가변상자의 사용을 고려하고 있다면, 여러분은 (구형 브라우저에서) 테스트를 수행해야 하고, 최대한 다양한 브라우저 사용자들이 수용할만한 사이트 방문 경험을 보장할 필요가 있습니다.

가변상자는 몇몇 씨에스에스 기능보다 다소 까다롭습니다. 예를 들어 브라우저에 씨에스에스 그림자 기능이 빠진 경우 해당 사이트을 여전히 사용할 수 있습니다. 그러나 가변상자 기능을 지원하지 않을 경우 조판이 완전히 깨져서 사용할 수 없게 됩니다.

크로스 브라우저 테스트 단원에서 크로스 브라우저 지원 문제를 극복하기 위한 전략에 대해 논의합니다.

요약정리

이로써 가변상자의 기본 안내서를 마감합니다. 재미있는 경험이었기 바라며, 당신이 학습 진도를 더해 갈수록 가변상자를 자유자제로 다룰 수 있게 될 겁니다. 다음으로 씨에스에스 조판의 또 다른 중요한 측면인 씨에스에스 격자를 살펴볼 것입니다.