서론
Flexible Box module. 일명 flexbox라고 불리는 모델은 인터페이스 내의 요소 간 공간 배분과 각종 정렬 기능을 제공하기 위한 레이아웃 모델로 설계되었다. 쉽게 말하자면 요소들을 자유 자재로 옮겨 놓는, 그냥 레이아웃 배치 전용 속성이다. 개인적으로는 레이아웃 정렬 옵션 정도로 생각하고 있다.
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
<div class="box5"><h1>다섯 번째 div</h1></div>
<div class="box6"><h1>여섯 번째 div</h1></div>
<div class="box7"><h1>일곱 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
}
.box1 { /* 다른 박스 번호들도 동일 */
background-color : yellow;
border : solid 10px blue;
height : 100px;
width : 300px;
}
이러한 flexbox는 부모 요소에 'display: flex'라는 것을 적어줌으로써 사용할 수 있다. 이것이 가장 기본이 되는 속성이다. 다만, flexbox에는 이외의 다양한 속성들이 존재한다.
이러한 속성은 선언 위치(자식&부모)에 따라 flex container(플렉스 컨테이너)와 flex item(플렉스 요소)로 나뉜다. flex container는 부모, 즉 전체적인 정렬이나 흐름에 대해서 정의한다. 반면 flex item는 자식, 세부적인 자식 요소의 순서나 크기에 대한 내용을 정의한다.
물론 이는 알아듣기 쉬운 의미에서 그런 것이고, 실제로는 문서의 영역에서 'display: flex'이 선언된 곳이 곧 flex container이다. flex item은 말 그대로 flex container 내부에 형상된 공간을 사용하는 요소이고 말이다. 참고로 flex item은 수가 많아서 중복 설정을 종종 해야하기에 클래스 선택자 사용이 많은 편이다.
아래는 해당 구분에 따라 목차를 나누어놓았다.
flex container
flex-direction
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
<div class="box5"><h1>다섯 번째 div</h1></div>
<div class="box6"><h1>여섯 번째 div</h1></div>
<div class="box7"><h1>일곱 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
flex-direction: column-reverse;
}
.box1 { /* 다른 박스 번호들도 동일 */
background-color : yellow;
border : solid 10px blue;
height : 100px;
width : 300px;
}
flex-direction 속성은 축을 설정하는 속성으로, 'flex-direction: 방향값'으로 사용한다.
해당 속성은 반드시 부모 요소에 적용해야 한다. 그리고 이러한 적용에는 주축(main axis)과 교차축(cross axis)이라는 개념이 필요하다.
- 주축: 말 그대로 기본적으로 플렉스 아이템이 쌓이는 방향이다.
row, row-reverse 방향값은 주축을 가로 방향(행, 좌우, ㅡ)으로 설정하는 것이다.
column & column-reverse 방향값은 주축을 세로 방향(열, 상하, ㅣ)으로 설정하는 것이다.
여기서 'reverse'가 붙어있는 방향값들은 순서를 뒤집는 값이다. 즉, 1-2-3-4-5가 아닌 5-4-3-2-1로 바꿔버린다. - 교차축: 주축을 가로지르는 수직 방향. 즉, 주축이 십자가가 되도록 그어지는 축이다.
주축이 어느 것을 선택하느냐에 따라 반대되는 값이 교차축이 된다.
예를 들어 설명하자면 주축이 y일 경우, 교차축은 x가 된다.
참고로 기본값은 그냥 row이다.
flex-wrap
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
<div class="box5"><h1>다섯 번째 div</h1></div>
<div class="box6"><h1>여섯 번째 div</h1></div>
<div class="box7"><h1>일곱 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
flex-wrap: wrap;
}
.box1 { /* 다른 박스 번호들도 동일 */
background-color : yellow;
border : solid 10px blue;
height : 100px;
width : 300px;
}
flex-wrap 속성은 자식 요소들의 크기나 수가 커졌을 때 여러 행에 나눌 것인지, 아니면 기존처럼 한줄에 우겨넣을 것인지를 결정하는 속성이다.
- wrap : 항목을 여러 줄로 분산시킨다.
- nowrap: 기본값으로, 모든 항목을 한 줄에 강제적으로 표시한다.
- wrap-reverse: wrap와 비슷한데, reverse라는 단어에서 알 수 있다시피 시작 지점과 끝 지점을 반대로 뒤집는다.
즉, flex-wrap은 여유 공간이 없을 때 줄바꿈을 할지 말지 결정한다고 보면 된다.
justify-content
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
<div class="box5"><h1>다섯 번째 div</h1></div>
<div class="box6"><h1>여섯 번째 div</h1></div>
<div class="box7"><h1>일곱 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.box1 { /* 다른 박스 번호들도 동일 */
background-color : yellow;
border : solid 10px blue;
}
justify-content 속성은 축의 좌우(수평) 방향 정렬을 어떻게 할 것인지를 지정하는 속성이다.
- flex-start: 기본값으로, 요소들을 시작점부터 차례대로 나열한다.
- flex-end: 요소들을 끝점부터 차례대로 나열한다.
- center: 요소들을 부모의 중앙 지점으로부터 나열한다.
- space-between: 요소들 사이(between)에만 여유 공간을 주고 나열한다.
- space-around: 요소들의 사이 뿐만 아니라, 요소들의 앞뒤 둘레(around)에도 여유 공간을 준다.
space-between에서 둘레에도 여유 공간을 주는 것이다. 다만, 둘레 부분과 사이 부분의 여유 공간은 동일하지 않다. 둘레 부분이 조금 더 작으며, 이는 1:2 비율이다. - space-evenly: space-around 속성에서 둘레가 불균형했던 것을 해결한 속성이다.
즉, 둘레 부분도 사이 부분과 동일한 여유 공간 비율을 갖게 된다.
사용 방법은 'justify-content: 정렬형태값'이다.
align-content & align-items
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div__</h1></div>
<div class="box3"><h1>세 번째 div___</h1></div>
<div class="box4"><h1>네 번째 div_____</h1></div>
<div class="box5"><h1>다섯 번째 div_____</h1></div>
<div class="box6"><h1>여섯 번째 div______</h1></div>
<div class="box7"><h1>일곱 번째 div________</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
height: 550px;
width: 850px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
/*
align-content: flex-start;
align-content: flex-end;
align-content: center;
align-content: space-between;
align-content: space-around;
align-content: stretch;
*/
}
.box1 { /* 다른 박스 번호들도 동일 */
background-color : yellow;
border : solid 10px blue;
}
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
height: 550px;
width: 850px;
display: flex;
align-items: flex-start;
/*
align-items: flex-start;
align-items: flex-end;
align-items: start;
align-items: end;
align-items: center;
align-items: baseline;
align-items: stretch;
*/
}
.box1 { /* 다른 박스 번호들도 동일 */
background-color : yellow;
border : solid 10px blue;
}
align-content와 align-items는 서로 비슷한 속성이다. 교차축의 상하(수직) 방향 정렬을 어떻게 할 것인지를 지정하는 속성이다.
- align-content: 수직축의 아이템에 대한 상하 방향 정렬을 어떻게 할 것인지 지정한다.
여러 줄에 있는 아이템 간의 사이 공간 및 주변 공간 분포를 결정하는 속성이라 할 수 있다.
즉, align-content는 flex-wrap: wrap를 사용함으로써 요소를 2줄 이상으로 만들고 그것을 수직 정렬한다고 보면 된다.
값으로는 flex-start, flex-end, center, space-between, space-around, stretch를 사용할 수 있다. - align-items: align-content와 비슷하지만, align-content와 다르게 한 줄을 기준으로 정렬한다.
값으로는 align-items: flex-start, flex-end, center, baseline, stretch를 사용할 수 있다. - align-self: 위의 2개 속성은 부모 요소의 자식 전체를 묶어서 정렬한다. 그러나 align-self은 개별적인 자식 요소마다 각각 다른 정렬을 지정할 수 있다.
값으로는 flex-start, flex-end, center, baseline, stretch를 사용할 수 있다.
여기서 stretch 값은 2개 속성의 기본 값으로(사실 normal이라는 동일한 값도 있다.), 요소가 나머지 공간을 차지할 수 있도록 강제로 늘리는 것이다. 당연하지만, 늘어나는 과정에서 일부 요소의 내부적인 요소(텍스트, 이미지 등)의 크기가 이웃한 것과 크게 달라질 수도 있다.
flex item
align-self
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>flex-start div</h1></div>
<div class="box3"><h1>flex-end div</h1></div>
<div class="box4"><h1>center div</h1></div>
<div class="box5"><h1>baseline div</h1></div>
<div class="box6"><h1>stretch div</h1></div>
<div class="box7"><h1>auto div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
height: 550px;
width: 850px;
display: flex;
align-items: flex-start;
}
.box1 {
background-color : yellow;
border : solid 10px blue; /*미설정 기본*/
}
.box2 {
background-color : yellow;
border : solid 10px blue;
align-self: flex-start;
}
.box3 {
background-color : yellow;
border : solid 10px blue;
align-self: flex-end;
}
.box4 {
background-color : yellow;
border : solid 10px blue;
align-self: center;
}
.box5 {
background-color : yellow;
border : solid 10px blue;
align-self: baseline;
}
.box6 {
background-color : yellow;
border : solid 10px blue;
align-self: stretch;
}
.box7 {
background-color : yellow;
border : solid 10px blue;
align-self: auto;
}
align-content와 align-items와 비슷한 속성이다. 다만, 해당 2개 속성은 부모 요소의 자식 전체를 묶어서 정렬한다. 그러나 align-self은 개별적인 자식 요소마다 각각 다른 정렬을 지정할 수 있다. 즉, 해당 2개 속성의 개별적인 버전. 교차축을 기준으로 요소를 자체 정렬하는 속성이라고 보면 된다. 그렇기에 플렉스 컨테이너가 아닌 플렉스 아이템(FI)에 속한다.
값으로는 flex-start, flex-end, center, baseline, stretch, auto를 사용할 수 있다.
또한, auto가 기본값이다. auto의 경우 기본적으로 상위 컨테이너의 align-items 속성을 상속 받아 따라간다. 그러나 상위 컨테이너가 없는 경우 stretch를 상속한다.(stretch가 align-items의 기본값이므로.)
flex-grow
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
}
.box1 {
background-color : yellow;
border : solid 10px blue;
}
.box2 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 1;
}
.box3 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 0;
}
.box4 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 2;
}
flex-grow는 item의 증가 너비 비율을 설정한다. 플렉스 아이템의 비율적인 증가를 담당한다고 보면 된다.
기본 값은 0인데, 이는 해당 속성이 적용되지 않을 때도 마찬가지이다. 또한, 값이 0인 상태에서는 아이템이 채워지지 않은 곳이 여백으로 남게 된다. 당연하게도 flex-grow 속성을 적용하면 여백이 메워지게 각 아이템들이 비율에 맞게 늘어난다.
소수점 값을 지정할 수 있다. 당연하게도 이에 따라 상세한 공간 비율을 설정할 수 있다. 그리고 아이템이 가변 너비가 아니면 별 효과는 없다.
flex-shrink
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
}
.box1 {
background-color : yellow;
border : solid 10px blue;
width: 350px;
flex-shrink : 1;
}
.box2 {
background-color : yellow;
border : solid 10px blue;
width: 250px;
flex-shrink : 1;
}
.box3 {
background-color : yellow;
border : solid 10px blue;
width: 250px;
flex-shrink : 1;
}
.box4 {
background-color : yellow;
border : solid 10px blue;
width: 250px;
flex-shrink : 2;
}
flex-grow와 반대인 플렉스 아이템의 축소를 담당하는 속성이다. 즉, 축소 너비 비율을 설정한다.
flex-grow가 남는 공간을 사용하기 위해 분배하는 속성이라면 flex-shrink는 부족한 공간을 사용하기 의해 크기를 줄이는 속성이다. 즉, 줄어든 영역을 서로 차지하는 것으로 기능한다.
기본값은 1이며, 이는 각 아이템들의 비율이 같다는 걸 뜻한다. 0일 경우에는 아무런 효과도 일어나지 않는다.
flex-basis
<div class="mains">
<div class="box1"><h1>첫 번째 div</h1></div>
<div class="box2"><h1>두 번째 div</h1></div>
<div class="box3"><h1>세 번째 div</h1></div>
<div class="box4"><h1>네 번째 div</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
}
.box1 {
background-color : yellow;
border : solid 10px blue;
flex-basis : 0;
}
.box2 {
background-color : yellow;
border : solid 10px blue;
flex-basis : 30%;
}
.box3 {
background-color : yellow;
border : solid 10px blue;
flex-basis : 20%;
}
.box4 {
background-color : yellow;
border : solid 10px blue;
flex-basis : 40%;
}
flex-basis는 플렉스 아이템의 크기를 설정하는 속성이다. 정확하게는 기본 너비/높이 설정이며, width/height와 비슷하다고 볼 수 있다.
물론 완전히 같다면 해당 속성이 분리되어 있을 이유는 없을 것이다. width/height 와 다르게 flex-basis는 flex-direction(주축 설정)에 영향을 받는다. 정확하게는 높낮이 설정을 같이할 수 없기에 주축의 영향을 받는다.
flex-direction: row로 선언해두면 주축을 행에 맞추게 되는데, 이러면 아이템 너비를 설정한다.
flex-direction: column로 선언해두면 주축을 열에 맞추게 되는데, 이러면 아이템 높이를 설정한다.
또한, width/height 에 비해 적용 우선순위가 높다. 그러나 이 차이가 전부이기에 기존 width/height 를 flex-basis로 바꾼다고 해도 유의미한 결과를 못 얻을 수 있다.
해당 속성의 기본값은 auto이다. CSS의 수많은 auto처럼 내부 구성 요소에 따라 유연하게 크기가 조절된다고 보면 된다. 이는 아이템 자신이 갖고 있는 본연의 크기를 쓴다고 볼 수도 있다.
width와 마찬가지로 px, %, em, cm 등의 다양한 단위를 값에 사용할 수 있다.
다만, 값을 0으로 설정하면 flex-grow, flex-shrink를 기준으로 크기가 결정된다. 이는 auto와는 다소 다르다. 즉, 플렉스 컨테이너의 기준에서 남는 공간을 줘버리던지, 다른 아이템의 비율 때문에 비정상적으로 공간이 쪼그라드는 현상이 일어난다.
<div class="mains">
<div class="box1"><h1>첫 번째 div_</h1></div>
<div class="box2"><h1>두 번째 div_ _</h1></div>
<div class="box3"><h1>세 번째 div_ _ _ _ _ _</h1></div>
<div class="box4"><h1>네 번째 div_ _ _ _ _ _ _ _</h1></div>
</div>
.mains {
background-color : orange;
border : solid 5px brown;
margin : 15px;
padding : 15px;
display: flex;
}
.box1 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 1;
flex-basis : 0;
}
.box2 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 1;
flex-basis : 0;
}
.box3 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 1;
flex-basis : 0;
}
.box4 {
background-color : yellow;
border : solid 10px blue;
flex-grow : 1;
flex-basis : 0;
}
다만, 이를 이용한 흥미로운 기법도 존재한다. 바로 flex-basis : 0를 사용한 각 아이템에 동일한 flex-grow 값(1이나 2나 3 등으로 통일)을 선언해두는 것이다. 이렇게 되면 아이템 간에 서로 동일한 크기를 갖는다. 내부의 내용이 서로 다른 크기를 가져도 말이다.
이는 flex-grow : 1만 사용한 예시와 비교하면 확연한 차이를 보여준다. 확실하게 위의 이미지가 아래의 이미지에 비해 균등한 비율을 갖는 걸 알 수 있다.
garcon.log의 블로그
이러한 흥미로운 내용은 다음 블로그의 글을 살펴보다가 알게 되었다. 정말 요약 및 설명이 잘 되어 있다!
flex
위의 3개 플렉스 아이템 속성(flex-grow, flex-shrink, flex-basis)을 간편히 지정할 수 있는 단축 속성이다.
.flexitem1 { /* 내부 값이 1개임 */
flex: 2; /* 그냥 숫자만 있으면 flex-grow 속성 */
flex: 150px; /* 숫자+단위이면 flex-basis 속성 */
flex: 50%; /* 숫자+%도 마찬가지로 flex-basis 속성 */
}
.flexitem2 { /* 내부 값이 2개임 */
flex: 2 1; /* 1번 값은 무조건 flex-grow 속성, 2번 값은 숫자만 있으면 flex-shrink 속성 */
flex: 2 150px; /* 다만 2번 값에 숫자+단위가 있으면 flex-basis 속성 */
flex: 2 50%; /* 마찬가지로 2번 값에 숫자+%가 있으면 flex-basis 속성 */
}
.flexitem3 { /* 내부 값이 3개임 */
flex: 2 1 150px; /* flex-grow flex-shrink flex-basis 속성 순서대로 사용*/
}
'flex: 증가비율(flex-grow) 축소비율(flex-shrink) 기본크기(flex-basis)' 가 기본적인 사용법이다. 다만, 내부 값에 어떤 단위가 들어가느냐에 따라 속성이 변화하기도 한다.
여기서 주의해야 할 점이 하나 있는데, 바로 flex 내에서 flex-basis 부분이 생략되면 flex-basis가 0으로 잡히는 일이 발생한다. 당연하게도 그렇게 될 경우 해당 아이템의 크기는 급속도로 쪼그라 들 것이다... 물론 필요할 수도 있기에 상황에 따라서 잘 사용해야 할 것 같다.