플랙스박스 – Flexbox Layout
요소들이 가용 공간을 어떻게 효과적으로 채워 나갈지에 대한 아이디어에서 비롯된 CSS 메서드.
플롯(Float)과 포지셔닝(Position) 방식에서 나타나는 문제점, 그 문제를 해결하는 과정에서 필연적으로 만나게 되는 여러 부작용을 대부분 해소할 수 있다.
Flexbox에 대해 자세히 설명하는 좋은 사이트가 있으니 이 글에서는 주의 할 점과 즉시 사용할 수 있는 속성 시뮬레이팅을 중점적으로 소개한다.
- CSS Flexbox 완전 정리. 포트폴리오 만드는 날까지! – 드림코딩 엘리
- 플렉스 박스 레이아웃 – PoiemaWeb
- 이번에야말로 CSS Flex를 익혀보자 – 1분 코딩
Markup - Flexbox
자식 요소(Flex Item)를 감싸는 부모 요소(Flex Container)에 display: flex 혹은 display: inline-flex 속성값을 사용하여 이 요소들이 Flexbox 레이아웃임을 선언한다.
부모 요소 - Flex Container
Flexbox 레이아웃은 크게, 부모 요소와 자식 요소에 사용할 속성이 나뉘어 있다. 부모 요소의 속성 선언만으로도 작성자가 원하는 대부분의 일반적 요구를 만족시키며, 자식 요소의 속성으로 더욱 디테일한 후속 작업이 가능하다.
flex-direction
자식 요소를 어떤 방향성을 가지고 배치 할 지 결정하는 기본축을 선언한다. 이 기본축이 가로냐 세로냐에 따라 후술할 속성들의 정렬축이 결정된다.
기본값은 row, 측방은 가로다. 따라서 모든 자식 요소가 가로로 배치된다.
column의 측방은 세로다. 따라서 모든 자식 요소가 세로로 배치된다.
1
2
3
4
5
justify-content
기본축 방향으로 자식 요소를 정렬한다. 혼동하기 쉬운 요인은 아래와 같으니 유의한다.
- 아래 예제에서 자식 요소들이 가로로 배치되어 있다고 해서 justify-content 속성이 반드시 수평 방향으로만 정렬하는 것은 아니다. flex-direction의 기본축(row, column)에 따라 수평, 수직으로 방향성이 바뀐다. 난해하다면 더 아래 align-items 설명에서 추가 예문을 참고한다.
- 만일 자식 요소가 부모 요소의 공간에 꽉 차게 배치되어 있다면 아무런 효과를 볼 수 없다.
예제에는 없지만 justify-content: space-evenly 같은 추가 속성값이 있으니 추천 사이트를 통해 더 알아보도록 한다.
1
2
3
4
5
align-items
기본축의 교차축(반대 축) 방향으로 자식 요소를 정렬한다. 혼동하기 쉬운 요인은 아래와 같으니 유의한다.
- align-items 속성이 반드시 수직 방향으로만 정렬하는 것은 아니다. flex-direction에서 선언한 기본축의 반대 방향으로 정렬한다.
- 만일 자식 요소가 부모 요소의 공간에 꽉 차게 배치되어 있다면 아무런 효과를 볼 수 없다. 아래 예문에서도 일부 속성값에서 그런 현상을 볼 수 있다.
여기에 소개한 flex-flow 속성은 flex-direction, flex-wrap 속성의 단축 속성이다.
1
2
3
4
5
1
2
3
baseline의 경우가 난해할 수 있는데, 숫자 텍스트가 컨테이너의 baseline 측방을 암시적으로 나타내고 있다.
두 번째 예시에서는 align-items가 flex-direction: column 상태에서 가로 방향으로 정렬하는 것을 확인했다. 앞서 설명했던 justify-content도 flex-direction의 값이 row냐 column이냐에 따라 정렬 방향이 바뀐다는 것을 기억하자.
align-content
flex-wrap: wrap 속성에 의해 줄넘김 된 요소를 개별 단위에서 하나의 그룹 단위로 묶는다. 자식 요소가 줄넘김 없이 한 줄로만 이루어진 경우에는 아무 효과가 없다.
justify-content, align-items 속성값을 한꺼번에 가지고 있으며, 정렬 알고리즘은 align-items와 같이 기본축의 교차(반대) 방향이다.
다루는 속성이 많은 만큼 한번쯤 MDN 문서를 읽어보길 권한다.
1
2
3
4
5
6
7
8
9
10
11
flex-wrap
자식 요소의 줄넘김을 처리한다. 기본값은 nowrap으로 줄넘김 하지 않는다.
값이 wrap인 경우, 기본적으로 자식 요소 크기의 합이 부모 요소보다 클 때 줄넘김 하는데,
- 100px 크기의 자식 요소가 10개 있다(총 1000px)
- 부모 요소의 크기는 700px이다.
- 부모 요소에 7개의 자식 요소가 한 행을 이루고 나머지 3개의 요소는 개행한다.
1
2
3
4
5
6
7
gap
행과 열 사이의 간격(Gutter)을 설정한다.
첫 요소와 마지막 요소 사이만 보간하기에 그동안 flexbox 방식을 사용하지 않는 그리드 모듈 프레임워크에서 골치였던 래퍼(wrapper) 음수 마진 따위의 문제가 사라진다.
1
2
3
4
5
gap 속성은 row-gap, column-gap의 단축 속성으로, 행간과 열간을 일괄 적용한다. MDN 한글화 문서에 잘 설명되어 있으니 참고한다.
자식 요소 - Flex Item
부모 요소에서 전체 배치에 대한 큰 틀을 마련했다면, 자식 요소에 속성값을 추가해서 후속 처리를 할 수 있다. 작성자가 원하는 경우의 수 대부분을 구현할 수 있고, 보통 아래의 경우에 매우 유용하다.
- 전체 가로로 정렬된 요소에서 특정 요소만 세로 정렬을 추가하고 싶다. 반대의 경우도 마찬가지.
- 특정 뷰포트(예를들어 모바일)에서는 요소의 위치를 바꾸고 싶다.
- 뷰포트 크기가 달라질 때, 요소 고유의 배율을 동적으로 조절하고 싶다.
- 플롯(Float), 미디어 쿼리, CSS 함수 혹은 자바스크립트 의존 없이 요소의 고유 크기를 유지하다가, 형제 요소가 없거나 없어질 경우 너비나 높이 100% 값을 동적으로 가지고 싶다.
아래에 설명하는 속성은 반드시 부모 요소에 display: flex가 선언되어야 한다.
order
컨테이너 안에서 아이템이 나열되는 순서를 나타낸다. 숫자가 작을수록 앞에, 클수록 끝에 위치한다. 음수 사용이 가능하며, 음수가 클수록 앞에 위치한다.
order 속성이 선언되면, HTML이나 CSS에서 구문을 어떤 순서에 따라 작성했는지와 상관없이, 오직 order에 선언된 값에 의해서만 순서가 정해진다.
1
2
3
4
5
배치 된 순서 그대로 역방향 정렬하는 flex-direction의 row-reverse, column-reverse와는 달리, order는 HTML 작성 순서와 관계없이 원하는 순서로 완전히 재배치 한다.
보통 order로 변경된 요소들은 그 위치에 맞게 스타일을 조정해야 하는 작업이 불가피한데, order 요소가 많을수록 코드의 자연스러운 흐름에 문제가 생기고 작업량이 많아지는 부분은 주의해야 한다.
flex-grow
뷰포트 크기가 달라질 때, 요소 고유의 크기 배율을 동적으로 처리하는 Flexbox의 핵심. 이제부터는 앞서 소개한 3개의 추천 사이트를 통해 원리를 이해하는 것이 바람직하다.
- 이번에야말로 CSS Flex를 익혀보자 – 1분 코딩
- CSS Flexbox 완전 정리. 포트폴리오 만드는 날까지! – 드림코딩 엘리
- 플렉스 박스 레이아웃 – PoiemaWeb
기본 값은 0, 음수는 무효하며, 값이 2라고 해서 반드시 다른 요소의 2배수를 가지는 것은 아니다. 크기가 모두 다른 각각의 요소가 점유하는 전체 공간에 대한 확대 인자라는 점에 유의한다.
*한 쪽 요소의 크기는 고정하고, 다른 한 쪽의 크기를 동적으로 구성하는 레이아웃의 용례에 대해서는 flex-shirink와 함께 다룬다.
1
2
3
4
5
flex-shrink
기본 값은 1, 음수는 무효하며, 값이 0이면 자신을 포함하고 있는 가용 공간의 계산된 값에서 해제되어 본래 CSS에 선언된 값을 갖는다.
이 속성은 실제로 뷰포트 크기를 줄여가며 확인하는 것이 가장 체감하기 좋다.
유의 할 점은, flex-shrink: 0으로 해제되어 기존에 선언되어 있는 크기(예를들어 width: 150px)로 돌아가면, min-width 속성을 따로 선언하지 않는 이상 뷰포트가 작아질수록 그 크기가 유지되지 않고 요소의 최소 크기까지 줄어든다.
1
2
3
4
5
고정폭 + 가변폭 블록
앞서 언급한 바와 같이, 한 요소는 고정폭을 유지하고 다른 한 요소는 뷰포트에 따라 동적으로 변하는 가변폭 블록에 대해 생각해 보자. 보통 이것은 Flexbox를 사용하지 않더라도 쉽게 구현한다.
Flexbox를 사용한다면 아래와 같다. 실제 작동을 확인하려면 여기를 보자.
어떤 경우에는 조건부 로직에 따라 특정 요소를 화면에서 제거해야 할 때가 있다. 예를들어 모바일 화면에서는 right 요소가 없어져야 하는 상황. 혹은 반대의 상황.
그렇다면, 없어진 요소의 빈 공간을 남은 요소가 채워야 하는데 위 예문의 HTML 코드에서 right 요소를 없애면 left 요소는 기존 크기를 유지하고 있다.
문제 해결을 위해 Flexbox를 사용하지 않고 직접 코드를 작성하다보면 플롯(Float), 미디어 쿼리, CSS 함수 혹은 자바스크립트 의존 없이는 만만치 않다는 것을 느낀다.
이제 추가 코드나 Hacky한 방법을 쓰지 말고 코드를 조금만 조정한다. 실제 작동을 확인하려면 여기를 보자.
flex-basis
아이템의 기본 크기 값을 선언한다. 여기서 크기란, flex-direction: row인 경우 너비, flex-direction: column인 경우 높이를 뜻한다.
단위로는 <length> (px, em, rem..), %(퍼센테이지) 모두 사용할 수 있고 그 밖에 auto, fit-content 등의 고유 값도 존재한다.
기본값은 auto이며 flexbox에 의해 계산된 크기다. 0인 경우 width, height 등의 다른 속성 선언에 따른다.
선언한 값이 auto가 아니면 width(혹은 height) 값보다 우선한다.
속성 테스트는 후술 할 flex 속성에서 해보기 바란다.
flex
flex-grow, flex-shrink 그리고 flex-basis 속성을 한번에 선언하는 단축 속성이다. 기본 값은 0 1 auto이며, flex-shrink와 flex-basis는 옵션 값으로서, 기재하지 않으면 자동으로 기본 값이 선언된다.
다른 css 단축 속성보다 직관적으로 다가오지 않으므로 속성별로 선언하는 편을 권장한다. 만일 사용하겠다면 MDN의 한글화 문서가 간단 명료하게 잘 설명했으니 참고한다.
1
2
align-self
부모 요소의 기본축과 반대되는 교차축으로 독자적인 정렬 값을 가질 수 있다. 이것은 align-items의 동작 방식과 일맥상통 하는데, 모든 자식 요소가 가로로 정렬되어 있다면, 특정 자식요소만 세로 정렬을 추가할 수 있다. 혹은 그 반대.
부모 요소가 flex-direction: row를 선언했다면 수직축으로, flex-direction: column을 선언 했다면 수평축으로 추가 정렬 할 수 있다.
위 예제는 flex-direction: row를 선언했으므로 자식 요소가 수직축으로 추가 정렬한다.
재차 강조하지만, 이 속성 역시 어느 한 방향에 국한 된 것이 아니라, 기본축의 교차 방향으로 정렬한다는 점에 유의한다.
1
2
3
4
5