CSS에서 한번 익혀두면 두고두고 사용할 수 있는 Flexbox를 알아보려고 합니다. 지금 당장 본인의 코드에서 사용하고 있지 않다고 하더라도 이번만큼은 반드시 알아두면 도움이 될 거라 생각합니다. 그럼 지금부터 같이 Flexbox를 알아볼게요.
물론 Flexbox를 모른다고 해서 레이아웃 구성을 못 하는 것은 아니지만 확실히 알고 있으면 우리에게 많은 이점을 주는 것은 사실입니다. 밥을 숟가락을 이용해서 먹는 것과 손으로 먹는 느낌이랄까요?
한 번만 시간 내서 천천히 읽다 보면 어느 순간 Flexbox는 이미 내 코드가 되어 있을거에요.
그럼 우리는 이렇게 외치겠죠. Flex 해버렸잖아~~
그럼 지금부터 진짜 Flexbox에 대하여 알아보도록 하겠습니다.
전체적인 내용은 참조 내용에 제가 읽기 편하도록 내용을 수정하고 추가적으로 필요한 내용은 첨언하였습니다.
💡 flexbox란?
flexbox는 뷰포트나 요소의 크기가 불명확하거나 동적으로 변할 때에도 효율적으로 요소를 배치, 정렬, 분산할 수 있는 방법을 제공하는 CSS3의 새로운 레이아웃 방식으로 flexbox의 장점을 한 마디로 표현하면 '복잡한 계산 없이 요소의 크기와 순서를 유연하게 배치할 수 있다'라고 할 수 있습니다. 정렬, 방향, 순서, 크기 등을 유연하게 조절할 수 있기 때문에 별도의 분기 처리를 줄일 수 있고, CSS만으로 다양한 레이아웃을 구현할 수 있습니다.
✔ 부모 요소와 자식 요소에 정의하는 속성 구분
flexbox에서 사용하는 속성은 부모 요소인 flex container에 정의하는 속성과 자식 요소인 flex item에 정의하는 속성으로 나누어지게 됩니다. 전체적인 정렬이나 흐름에 관련된 속성은 flex container에 정의하고, 자식 요소의 크기나 순서에 관련된 속성은 flex item에 정의합니다.
- flex container 속성: flex-direction, flex-wrap, justify-content, align-items, align-content
- flex item 속성: flex, flex-grow, flex-shrink, flex-basis, order
✔ flexbox 지원 범위
flexbox는 Internet Explorer 10 이상을 지원하지만 Internet Explorer 10 이상이 완전히 지원하지는 않아 Internet Explorer 10과 Internet Explorer 11에서 버그가 발견되기도 한다. 그래서 PC용 서비스에 flexbox를 적용하기에는 아직 이른 감이 있습니다.
모바일 브라우저의 flexbox 지원율은 매우 높아 대부분의 iOS용 브라우저와 Android용 브라우저가 지원한다고 생각해도 됩니다.(Can I use 사이트의 'flex' 검색 결과 참고).
✔ flexbox의 구성
flexbox는 복수의 자식 요소인 flex item과 그 상위 부모 요소인 flex container로 구성됩니다.
flexbox를 만드는 방법은 간단합니다. 정렬하려는 요소의 부모 요소에 다음과 같이 display: flex 속성을 선언하면 됩니다.
.flex_container {
display: flex;
}
전체 영역을 감싸고 있는 부분이 Flex Container(플렉스 컨테이너)가 되고 그 하위 자식 요소들이 Flex Item(플렉스 아이템)이 됩니다. 컨테이너가 Flex의 영향을 받는 전체 공간이고, 설정된 속성에 따라 각각의 아이템들이 어떤 형태로 배치되는 것”이라고 생각하면 조금은 더 쉽게 이해하실 수 있습니다.
Flex에서 Item들이 배치된 방향의 축을 메인축(Main Axis), 메인축과 수직인 축을 수직축 또는 교차축(Cross Axis)이라고 불러요.
Flex item은 주축(main axis)에 따라 정렬되는데 주축의 방향은 flex container의 flex-direction 속성으로 결정합니다.
👍 배치 방향 설정 : flex-direction
아이템들이 배치되는 축의 방향을 결정하는 속성입니다. 메인축의 방향을 가로 또는 세로로 할지를 정하는 속성입니다. flex-direction 속성을 따로 지정하지 않으면 기본값인 row가 적용됩니다. 속성 값 row는 주축의 방향을 왼쪽에서 오른쪽 방향으로 흐르게 하며 flex-direction 속성의 또 다른 속성 값인 column은 주축의 방향을 위에서 아래 방향으로 흐르게 합니다.
.container {
flex-direction: row;
/* flex-direction: column; */
/* flex-direction: row-reverse; */
/* flex-direction: column-reverse; */
}
주축은 flex-direction에 의해 정의되며 4개의 값을 가질 수 있습니다.
- row : 아이템들이 행(가로) 방향으로 배치
- row-reverse : 아이템들이 역순으로 가로 배치
- column : 아이템들이 열(세로) 방향으로 배치
- column-reverse : 아이템들이 역순으로 세로 배치
보다 자세한 설정은 아래 예시 이미지를 보면서 이해하면 좀 더 쉽게 이해가 될 거 같아요.
row 혹은 row-reverse를 선택하면 주축은 인라인 방향으로 행을 따릅니다.
column 혹은 column-reverse을 선택하면 주축은 페이지 상단에서 하단으로 블록 방향을 따릅니다.
교차축은 주축에 수직 하므로, 만약 flex-direction(주축)이 row 나 row-reverse 라면 교차축은 열 방향을 따릅니다.
주축이 column 혹은 column-reverse 라면 교차축은 행 방향을 따릅니다.
flex 요소를 정렬하고 끝을 맞추(justify)려면 어느 축이 어느 방향인지 이해하는 것이 중요합니다; flexbox는 주축, 교차축을 따라 항목을 정렬하고 끝을 맞추는 각종 속성들을 적용하는 방식으로 동작합니다.
👍 줄넘김 처리 설정 : flex-wrap
container에 요소들을 한 줄에 담을 여유 공간이 없을 때 요소(item)의 줄바꿈을 어떻게 할지 결정하는 속성입니다.
.container {
flex-wrap: nowrap;
/* flex-wrap: wrap; */
/* flex-wrap: wrap-reverse; */
}
- nowrap: 기본 속성값으로 줄바꿈을 하지 않음
- wrap : Item 요소들이 줄바꿈 처리 됨.
- wrap-reverse : 요소들이 줄바꿈 처리 되며 역순으로 배치.
- flex-flow: flex-direction과 flex-wrap을 한꺼번에 지정할 수 있는 단축 속성(flex-direction, flex-wrap의 순으로 한 칸 공백 후 사용)
👍 메인축 방향 정렬 : justify-content
justify-content (en-US) 속성은 주축을 따라 flex 항목 행을 정렬하는 방식을 지정합니다.
- flex-start : 기본값, Item을 시작점으로 정렬하며 flex-direction이 row(가로 배치)일 때는 왼쪽, column(세로 배치)일 때는 위로 정렬
- flex-end : Item을 끝점으로 정렬, flex-direction이 row(가로 배치)일 때는 오른쪽, column(세로 배치)일 때는 아래로 정렬.
- center : Item을 가운데로 정렬
- space-around : Item의 “둘레(around)”에 균일한 간격으로 배치
- space-between : Item의 사이(between)에 균일한 간격으로 배치
- space-evenly : Item의 사이와 양 끝에 균일한 간격으로 배치, IE와 엣지(Edge)에서는 지원되지 않음
.container {
justify-content: flex-start;
/* justify-content: flex-end; */
/* justify-content: center; */
/* justify-content: space-between; */
/* justify-content: space-around; */
/* justify-content: space-evenly; */
}
space-between, space-around, space-evenly는 비슷한듯 하면서 살짝 다른데 아래 그림을 통해 차이점을 비교해 보세요.
👍 수직축 방향 정렬 : align-items
수직축 방향으로 아이템을들 정렬하는 속성으로 수직 방향의 정렬이라고 생각하시면 됩니다.
.container {
align-items: stretch;
/* align-items: flex-start; */
/* align-items: flex-end; */
/* align-items: center; */
/* align-items: baseline; */
}
- stretch : 기본값, item이 수직축 방향으로 끝까지 쭈욱 늘어남
- flex-start : item을 시작점으로 정렬, flex-direction이 row(가로 배치)일 때는 위, column(세로 배치)일 때는 왼쪽으로 정렬
- flex-end : item을 끝으로 정렬 flex-direction이 row(가로 배치)일 때는 아래, column(세로 배치)일 때는 오른쪽으로 정렬
- center : item을 가운데로 정렬
👍 여러 행 정렬 : align-content
flex-wrap: wrap;이 설정된 상태에서, 아이템들의 행이 2줄 이상 되었을 때의 수직축 방향 정렬을 결정하는 속성입니다.
.container {
flex-wrap: wrap;
align-content: stretch;
/* align-content: flex-start; */
/* align-content: flex-end; */
/* align-content: center; */
/* align-content: space-between; */
/* align-content: space-around; */
/* align-content: space-evenly; */
}
💡 flex 항목에 지정 가능한 속성들
500 픽셀의 크기를 갖는 flex 컨테이너 내에 100 픽셀 크기의 자식 세 개가 존재할 때, 사용 가능한 공간 200 픽셀이 남게 됩니다. 기본적으로 flexbox는 이 공간을 마지막 자식 요소 다음에 빈 공간으로 남겨둡니다.
위의 세 가지 속성을 변경한다는 것은 flex 항목에게 사용 가능한 공간을 분배하는 방식을 변경하는 것입니다. 사용가능한 공간 개념은 flex 항목을 정렬할 때 특히 중요합니다.
👍 유연한 박스의 기본 영역 : flex-basis
flex-basis는 Flex 아이템의 기본 크기를 설정합니다(flex-direction이 row일 때는 너비, column일 때는 높이).
flex-basis 속성은 항목의 크기를 결정합니다. 이 속성의 기본값은 auto이며, 이 경우 브라우저는 항목이 크기를 갖는지 확인합니다. 위의 사진 예시의 경우 항목의 크기가 100 픽셀이므로 flex-basis의 값으로 100 픽셀이 사용됩니다.
flex 항목에 크기가 지정되어 있지 않으면, flex 항목의 내용물 크기가 flex-basis 값으로 사용됩니다. 따라서 flex 컨테이너에서 display: flex 속성만을 지정하면 flex항목들이 각 내용물 크기만큼 공간을 차지하게 됩니다.
👍 유연하게 늘리기 : flex-grow
flex-grow는 아이템이 flex-basis의 값보다 커질 수 있는지를 결정하는 속성이에요.
flex-grow에는 숫자 값이 들어가는데, 몇이든 일단 0보다 큰 값이 세팅이 되면 해당 아이템이 유연한(Flexible) 박스로 변하고 원래의 크기보다 커지며 빈 공간을 메우게 됩니다.
첫 항목의 flex-grow 값을 2로 지정하고 나머지 두 개의 항목을 1로 지정한다면 각 항목에 지정된 flex-grow 값의 비율에 따라 남은 공간이 분배됩니다. 각 항목의 flex-grow 비율이 2:1:1 이므로 첫 항목에게 100 픽셀, 두 번째와 세 번째 항목에게 50 픽셀씩 분배됩니다. flex-grow에 들어가는 숫자의 의미는, 아이템들의 flex-basis를 제외한 여백 부분을 flex-grow에 지정된 숫자의 비율로 나누어 가진다고 생각하시면 됩니다.
아래 실제 코드가 적용된 예시와 그림을 통해 이해해 봅시다.
/* 1:2:1의 비율로 세팅할 경우 */
.item:nth-child(1) { flex-grow: 1; }
.item:nth-child(2) { flex-grow: 2; }
.item:nth-child(3) { flex-grow: 1; }
각 아이템의 콘텐츠가 “AAAAA”, “B”, “CCC”로 원래의 크기가 다르기 때문에 전체 아이템의 크기가 살짝 애매한 비율로 보이지만, 여백의 비로 생각해 보면 정확히 1:2:1이죠! 정수뿐 아니라 3.141592 같은 소수도 가능합니다.
👍 유연하게 줄이기 : flex-shrink
flex-grow 속성이 주축에서 남는 공간을 항목들에게 분배하는 방법을 결정한다면 flex-shrink 속성은 주축의 공간이 부족할 때 각 항목의 사이즈를 줄이는 방법을 정의합니다. 만약 flex 컨테이너가 flex 항목을 모두 포함할 만큼 넉넉한 공간을 갖고 있지 않고 flex-shrink 값이 양수이면 flex 항목은 flex-basis에 지정된 크기보다 작아집니다. 또한, flex-grow 속성과 마찬가지로 더 큰 flex-shrink 값을 갖는 항목의 사이즈가 더 빨리 줄어듭니다.
.item {
flex-basis: 150px;
flex-shrink: 1; /* 기본값 */
}
👍 flex
flex-grow, flex-shrink, flex-basis를 한 번에 쓸 수 있는 축약형 속성입니다.
이 세 속성들은 서로 관련이 깊기 때문에, 이 축약형을 쓰는 편이 여러모로 편리합니다.
.item {
flex: 1;
/* flex-grow: 1; flex-shrink: 1; flex-basis: 0%; */
flex: 1 1 auto;
/* flex-grow: 1; flex-shrink: 1; flex-basis: auto; */
flex: 1 500px;
/* flex-grow: 1; flex-shrink: 1; flex-basis: 500px; */
}
주의할 점은, flex: 1; 이런 식으로 flex-basis를 생략해서 쓰면 flex-basis의 값은 0이 됩니다.
축약형 flex로 좀 더 예시를 들어 볼게요.
.item {
flex: 1 1 0;
}
.item:nth-child(2) {
flex: 2 1 0;
}
flex-basis: 0; 으로, 기본 점유 크기를 0으로 만들어버려 결국 전체 크기를 1:2:1로 나누어 가져서, 영역 자체의 크기가 정확히 1:2:1의 비율로 설정되었습니다.
여백의 비가 아닌, 영역 자체를 원하는 비율로 분할하기를 원한다면 이렇게 flex-basis을 0으로 하면 손쉽게 처리할 수 있어요.
flex-wrap과 flex-basis를 이용해서 2단 컬럼의 사각형 목록을 만들어 볼게요.
.container {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 1 1 40%;
}
👍 수직축으로 아이템 정렬: align-self
align-items의 아이템 버전입니다. align-items가 전체 아이템의 수직축 방향 정렬이라면, align-self는 해당 아이템의 수직축 방향 정렬입니다.
.item {
align-self: auto;
/* align-self: stretch; */
/* align-self: flex-start; */
/* align-self: flex-end; */
/* align-self: center; */
/* align-self: baseline; */
}
기본값은 auto로, 기본적으로 align-items 설정을 상속받습니다.
align-self는 align-items보다 우선권이 있습니다. 전체 설정보다 각각의 개별 설정이 우선한다는 것, 외우지 않아도 자연스럽게 다가오죠? auto 외의 나머지 값들은 align-items와 동일합니다.
👍 배치 순서 : order
각 아이템들의 시각적 나열 순서를 결정하는 속성이에요.
숫자 값이 들어가며, 작은 숫자일수록 먼저 배치됩니다. “시각적” 순서일 뿐, HTML 자체의 구조를 바꾸는 것은 아니므로 접근성 측면에서 사용에 주의하셔야 합니다. 시각 장애인분들이 사용하는 스크린 리더로 화면을 읽을 때, order를 이용해 순서를 바꾼 것은 의미가 없다는 것을 기억해 주세요.
.item:nth-child(1) { order: 3; } /* A */
.item:nth-child(2) { order: 1; } /* B */
.item:nth-child(3) { order: 2; } /* C */
💡 FlexBox를 활용한 10가지 레이아웃(Layout) 사례
이 글에서는 실무에서 많이 사용하는 다음 10가지 레이아웃을 flexbox로 구현하는 방법을 소개합니다. 이 레이아웃은 기존의 display 속성이나 float 속성, position 속성 등으로는 구현이 어렵거나 구현이 불가능하지만 flexbox를 사용하면 쉽게 구현할 수 있습니다.
- 레이아웃 1 - 스크롤 없는 100% 레이아웃
- 레이아웃 2 - 내비게이션 영역
- 레이아웃 3 - 브라우저 화면 아래에 붙는 푸터
- 레이아웃 4 - 정렬이 다른 메뉴
- 레이아웃 5 - 폼 레이블 수직 중앙 정렬
- 레이아웃 6 - 중앙 정렬 아이콘
- 레이아웃 7 - 유동 너비 박스
- 레이아웃 8 - 말줄임과 아이콘
- 레이아웃 9 - 위아래로 흐르는 목록
- 레이아웃 10 - 가로세로 비율을 유지하는 반응형 박스
레이아웃 1 - 스크롤 없는 100% 레이아웃
스크롤 없는 100% 레이아웃은 전체 페이지를 구성할 때 자주 사용할 수 있는 레이아웃이다. 다음 그림과 같이 콘텐츠의 길이에 상관없이 브라우저 화면 전체를 채우는 레이아웃이다.
이 레이아웃에서 웹 페이지의 위에 있는 메뉴 영역의 높이는 고정되어 있습니다. 부모 영역에서 메뉴 영역을 뺀 나머지 영역 전체를 자식 요소가 채우게 됩니다. 콘텐츠의 길이가 길어지면 스크롤 막대가 브라우저가 아니라 콘텐츠 영역에 나타나게 됩니다.
스크롤 없는 100% 레이아웃을 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "1. 스크롤이 없는 100% 레이아웃"에서 확인할 수 있습니다.
.flex_container {
display: flex;
flex-direction: column;
height: 100%;
}
.flex_item {
flex: 1; /* flex: 1 1 0 */
overflow: auto;
}
flex container(.flex_container 클래스)에 flex-direction: column 속성을 적용해 flex item을 수직으로 정렬하고 flex item(.flex_item 클래스)에는 flex: 1 속성을 적용해 flex item이 빈 공간을 채우게 합니다.
flex-direction: column 속성으로 수직 방향 정렬 설정
flexbox 레이아웃에서 주축의 방향은 왼쪽에서 오른쪽으로 향하는 수평 방향이 기본이지만 요소를 수직으로 배열하려면 주축이 위에서 아래로 향하게 해야 합니다. flex container의 flex-direction 속성의 값을 column으로 설정하면 주축의 방향을 바꿀 수 있습니다.
flex : 1 속성으로 자식 요소의 크기 확장
flex item에 적용한 flex 속성은 flex item의 크기와 관련된 속성이며, 다음과 같이 flex-grow 속성과 flex-shrink 속성, flex-basis 속성을 축약한 표현입니다.
앞의 그림에서 표현한 flex: 1 1 0 속성은 다음과 같은 flex-grow: 1 속성과 flex-shrink: 1 속성, flex-basis: 0 속성을 줄인 표현입니다.
.flex-item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
flex: 1 1 0은 다음과 같이 flex: 1로 표현할 수도 있습니다.
.flex-item {
flex: 1;
/* flex: 1 1 0 */
}
flex-grow 속성
flex-grow 속성은 flex item의 확장에 관련된 속성이다. 0과 양의 정수를 속성 값에 사용합니다.
속성 값이 0이면 flex container의 크기가 커져도 flex item의 크기가 커지지 않고 원래 크기로 유지되는데 flex container의 크기가 커질 때 flex item의 크기도 커지게 하려면 1 이상의 값을 속성 값으로 설정합니다. 속성 값이 1 이상이면 flex item의 원래 크기에 상관없이 flex container를 채우도록 flex item의 크기가 커집니다.
flex-shrink 속성
flex-shrink 속성은 flex item의 축소에 관련된 속성입니다. 0과 양의 정수를 속성 값에 사용하며 기본값은 1입니다.
속성 값이 0이면 flex container의 크기가 flex item의 크기보다 작아져도 flex item의 크기가 줄어들지 않고 원래 크기로 유지됩니다. 속성 값이 1 이상이면 flex container의 크기가 flex item의 크기보다 작아질 때 flex item의 크기가 flex container의 크기에 맞추어 줄어들게 됩니다.
flex-basis 속성
flex-basis 속성은 flex item의 기본 크기를 결정하는 속성으로 기본값은 auto입니다.
width 속성에서 사용하는 모든 단위(px, %, em, rem 등)를 속성 값에 사용할 수 있으며 flex-basis 속성의 값을 30px이나 30%와 같이 설정하면 flex item의 크기가 고정됩니다.
flex-basis 속성에서 auto와 함께 자주 사용하는 속성 값이 0으로 flex-basis 속성의 값을 0으로 설정하면 flex item은 절대적 flex item(absolute flex item)이 되어 flex container를 기준으로 크기가 결정됩니다.
주의
flex-basis 속성의 값을 0으로 선언할 때에는 flex-basis: 0px, flex-basis: 0%와 같이 단위도 함께 설정해야 합니다.
flex-basis 속성의 값을 auto로 설정하면 flex item은 상대적 flex item(relative flex item)이 되어 콘텐츠의 크기를 기준으로 크기가 결정됩니다.
flex: 1의 의미
flex-grow 속성과 flex-shrink 속성, flex-basis 속성을 축약해서 flex 속성으로 표현할 때 flex: 1 속성은 flex: 1 1 0 속성을 의미합니다. 즉, flex-grow 속성의 값이 '1'이고 flex-shrink 속성의 값이 '1'이기 때문에 flex container의 크기에 따라 flex item의 크기도 커지거나 작아진다는 의미입니다.
flex 속성의 값으로 정수 하나만 선언하면 선언한 값은 flex-grow 속성의 값이 됩니다. 나머지는 기본값인 flex-shrink: 1 속성과 flex-basis: 0 속성이 적용됩니다. 다시 말해 flex 속성에 한 개의 정숫값만 있으면 이것은 flex-grow 속성의 값만 지정하는 단축 속성입니다. 즉, flex: 2는 flex: 2 1 0을, flex: 3은 flex: 3 1 0을 나타냅니다.
레이아웃 2 - 내비게이션 영역
내비게이션은 웹 페이지에서 자주 사용하는 레이아웃입니다. 다음 그림과 같이 메뉴의 대부분을 내비게이션 영역의 왼쪽으로 정렬하고, 1~2개의 메뉴만 오른쪽으로 정렬한 내비게이션을 쉽게 볼 수 있다. 주로 GNB(global navigation bar)에 해당하는 요소나 로그인 버튼을 오른쪽으로 정렬합니다.
내비게이션 영역을 구현하는 기본 CSS는 다음과 같다. 구현 예제는 CodePen 사이트의 "2. 네비게이션"에서 확인할 수 있다.
.flex-container {
display: flex;
}
.flex-item {
flex: none;
/* flex: 0 0 auto */
}
.flex-item-gnb {
margin-left: auto;
}
크기가 고정되어야 하는 flex item(.flex-item 클래스)에는 flex: none 속성을 적용하고 오른쪽으로 정렬할 GNB나 로그인 버튼에 해당하는 요소(.flex-item-gnb 클래스)에는 margin-left: auto 속성을 적용합니다.
flex: none 속성으로 자식 요소의 크기 고정
내비게이션 영역의 기본 구조에서는 'logo' 요소와 'search' 요소, 'gnb' 요소의 크기가 커지거나 작아지지 않게 디자인되었으며 flex item의 크기에 관련된 속성인 flex 속성의 기본값은 flex: 0 1 auto입니다. 기본값을 적용하면 flex container의 크기가 flex item 전체의 크기보다 작아질 때 flex item의 크기가 작아지게 되며 flex item의 크기를 고정하려면 반드시 flex: none 속성을 적용해야 합니다.
flex: none은 flex-grow: 0 속성과 flex-shrink: 0 속성, flex-basis: auto 속성을 축약해 표현한 것이다. 하나의 정수를 사용해 축약하는 방법("flex: 1의 의미" 참고) 외에 세 개의 키워드인 initial, none, auto를 flex 속성의 값으로 설정해 속성을 축약할 수 있습니다.
flex 속성에 사용하는 키워드에 따라 축약되는 속성의 설정값은 다음과 같습니다.
flexflex-growflex-shrinkflex-basis
initial(기본값) | 0 | 1 | auto |
none | 0 | 0 | auto |
auto | 1 | 1 | auto |
양의 정수 | 숫자 | 1 | 0 |
flex 속성의 값에 따라 flex item의 크기는 다음과 같이 변합니다.
- initial(기본값): flex container의 크기가 작아지면 flex item의 크기가 작아진다. 하지만 flex container의 크기가 커져도 flex item의 크기는 커지지 않습니다.
- none: flex item의 크기가 커지거나 작아지지 않습니다. flex container의 크기에 영향을 받지 않고, flex item의 원래 크기를 유지합니다.
- auto: flex container의 크기에 맞추어 flex item의 크기가 커지거나 작아집니다.
- 양의 정수: flex container를 일정한 비율로 나눠 가지면서 flex container의 크기에 따라 flex item의 크기가 커지거나 작아집니다.
margin-left: auto 속성으로 자식 요소를 오른쪽에 배치
요소의 바깥 여백(margin)을 설정하는 속성에 속성값으로 auto를 적용하면 flexbox에서 flex item을 쉽게 배치할 수 있습니다. 예를 들어 margin: auto 속성을 적용하면 flex item의 바깥 여백이 자동으로 확장되어 flex item이 flex container의 가운데에 위치하게 됩니다.
flex item을 수평으로 배치할 때 다음과 같이 'auto' 속성값을 사용할 수 있습니다.
- margin-right: auto: 바깥 여백이 오른쪽의 모든 공간을 차지하기 위해 flex item을 오른쪽에서 왼쪽으로 밀음.
- margin: 0 auto: 바깥 여백이 flex item을 양쪽에서 밀기 때문에 flex item이 수평 중앙에 위치.
- margin-left: auto: 바깥 여백이 왼쪽의 모든 공간을 차지하기 위해 flex item을 왼쪽에서 오른쪽으로 밀음.
flex item을 수직으로 배치할 때 다음과 같이 'auto' 속성값을 사용할 수 있습니다.
- margin-bottom: auto: 바깥 여백이 아래쪽의 모든 공간을 차지하기 위해 flex item을 아래쪽에서 위쪽으로 밀음.
- margin: auto 0: 바깥 여백이 flex item을 위아래로 밀기 때문에 flex item이 수직 중앙에 위치.
- margin-top: auto: 바깥 여백이 위쪽의 모든 공간을 차지하기 위해 flex item을 위쪽에서 아래쪽으로 밀음.
flexbox에서 margin: auto 속성으로 레이아웃을 구현하는 방법이 핵(hack)이라고 생각하거나 버그를 일으키는 요인이 될 수도 있다고 생각할 수 있지만 margin: auto 속성은 오히려 flexbox 명세에서 권장하는 방법으로("CSS Flexible Box Layout Module Level 1"의 '8.1. Aligning with 'auto' margins' 참고) 자유롭게 사용해도 무방합니다.
레이아웃 3 - 브라우저 화면 아래에 붙는 푸터
웹 페이지에서 푸터(footer)는 보통 브라우저 화면의 맨 아래에 위치하는데 그렇기에 우리는 푸터가 화면의 아래에 딱 붙는 모습을 기대하지만, 콘텐츠의 길이가 화면보다 짧으면 푸터는 콘텐츠가 짧아진 만큼 위로 올라간 위치에 표시됩니다. flexbox를 사용하면 다음 그림과 같이 콘텐츠의 길이와 상관없이 항상 화면 아래에 표시되는 푸터를 만들 수 있습니다.
브라우저 화면 아래에 붙는 푸터를 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "3. 바닥에 붙는 푸터"에서 확인할 수 있습니다.
.flex-container {
display: flex;
flex-direction: column;
}
.flex_item {
margin-top: auto;
}
푸터에 해당하는 요소(.flex-item 클래스)에 margin-top: auto 속성을 적용합니다.
margin-top: auto 속성으로 자식 요소를 화면 아래에 배치
flex item에 margin-top: auto 속성을 적용하면 바깥 여백이 flex item을 위쪽에서 아래쪽으로 밀기 때문에 flex item이 아래쪽에 위치하게 됩니다.
레이아웃 4 - 정렬이 다른 메뉴
다음 그림에서 세 개의 자식 요소의 정렬이 각각 다릅니다. 첫 번째와 마지막 자식 요소는 부모 요소의 양쪽 끝에 붙어있고, 두 번째 자식 요소는 부모 요소의 중앙에 위치하고 있습니다.
정렬이 다른 메뉴를 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "4. 정렬이 다른 메뉴"에서 확인할 수 있습니다.
.flex-container {
display: flex;
justify-content: space-between;
}
flex container에 justify-content: space-between 속성을 적용합니다.
justify-content: space-between 속성으로 자식 요소를 일정한 간격으로 정렬
justify-content 속성은 주축을 기준으로 flex item을 수평으로 정렬합니다. 다음과 같은 5개의 속성 값으로 다양한 수평 정렬 레이아웃을 만들 수 있습니다.
- flex-start(기본값): 주축의 시작 부분을 기준으로 flex item을 정렬.
- center: 주축의 중앙을 기준으로 flex item을 정렬.
- flex-end: 주축의 끝부분을 기준으로 flex item을 정렬.
- space-around: 주축을 기준으로 flex item을 일정한 간격으로 정렬.
- space-between: 첫 번째와 마지막 flex item은 주축의 시작 부분과 끝부분에 정렬하고 나머지 flex item을 일정한 간격으로 정렬.
레이아웃 5 - 폼 레이블 수직 중앙 정렬
폼 요소의 레이블을 수직 중앙에 정렬하는 레이아웃으로 다음 그림과 같이 한 줄짜리 텍스트뿐만 아니라 두 줄 이상의 텍스트도 수직 중앙에 정렬됩니다.
폼 레이블 수직 중앙 정렬을 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "5. 폼 타이틀 수직 중앙정렬"에서 확인할 수 있습니다.
.flex_container {
display: flex;
align-items: center;
}
폼 레이블에 해당하는 요소(.flex_container 클래스)에 align-items: center 속성을 적용합니다.
align-items: center 속성으로 자식 요소를 교차축의 중앙에 정렬
align-items 속성은 주축을 기준으로 flex item을 수직으로 정렬합니다. 다음과 같은 5개의 속성 값으로 다양한 수직 정렬 레이아웃을 만들 수 있습니다.
- stretch(기본값): flex item의 높이를 늘려 flex container의 전체 높이를 채움.
- flex-start: 교차축의 시작 부분을 기준으로 flex item을 정렬.
- center: 교차축의 중앙을 기준으로 flex item을 정렬.
- baseline: 글꼴의 기준선인 baseline을 기준으로 flex item을 정렬.
- flex-end: 교차축의 끝부분을 기준으로 flex item을 정렬.
레이아웃 6 - 중앙 정렬 아이콘
자식 요소인 아이콘이 부모 요소의 정중앙에 위치하는 레이아웃 입니다.
중앙 정렬 아이콘은 두 가지 방법으로 구현할 수 있습니다.
첫 번째 방법은 다음과 같이 flex container에 align-items: center 속성과 justify-content: center 속성을 적용해 아이콘에 해당하는 flex item을 화면 정중앙에 정렬합니다.
.flex_container {
display: flex;
align-items: center;
justify-content: center;
}
두 번째 방법은 다음과 같이 아이콘에 해당하는 flex item에 margin: auto 속성을 적용해 아이콘이 화면 정중앙에 위치하게 합니다.
.flex_container {
display: flex;
}
.flex_item {
margin: auto;
}
구현 예제는 CodePen 사이트의 "6. 중앙정렬 아이콘"에서 확인할 수 있습니다.
레이아웃 7 - 유동 너비 박스
유동 너비 박스는 flex container인 부모 요소 크기에 따라 flex item인 자식 요소의 크기가 콘텐츠의 크기보다 줄어드는 레이아웃으로 부모 요소의 크기가 크다면 자식 요소의 크기는 콘텐츠 너비를 모두 수용할 수 있을 만큼 크지만 부모 요소의 크기가 줄어들어 콘텐츠의 크기보다 작아지면 자식 요소의 크기가 콘텐츠의 크기보다 줄어듭니다.
다음은 유동 너비 박스에서 부모 요소의 크기와 자식 요소의 크기가 변하는 모습입니다.
유동 너비 박스를 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "7. 유동 너비 박스"에서 확인할 수 있습니다.
.flex_container {
display: flex;
}
.flex_item {
/* flex : initial */
max-width: 300px;
}
flex item에 max-width: 300px만 선언합니다.
flex item의 크기에 관련된 속성인 flex 속성의 기본값은 0 1 auto 입니다. flex 속성을 설정하지 않으면 flex item에는 기본값이 적용됩니다. flex 속성의 기본값은 flex-grow: 0 속성과 flex-shrink:1 속성을 의미하며 flex container의 크기가 커질 때는 flex item의 크기는 변하지 않지만, flex container의 크기가 작아지면 flex item의 크기가 작아집니다.
레이아웃 8 - 말줄임과 아이콘
말줄임과 아이콘 레이아웃은 flex container인 부모 요소의 크기가 작아 flex item인 자식 요소의 텍스트를 모두 표시할 수 없을 때 줄임표(…)가 나타나게 하는 레이아웃입니다. 이때 텍스트 영역 옆에 있는 아이콘의 크기는 고정되어 있습니다.
줄임표와 아이콘을 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "8. 말줄임 + 아이콘"에서 확인할 수 있습니다.
.flex_container {
display: inline-flex;
max-width: 100%;
}
.text {
/*flex: 0 1 auto*/
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
flex container에 display: inline-flex 속성과 max-width: 100% 속성을 적용합니다.
display: inline-flex 속성으로 부모 요소를 인라인 블록 요소로 만들기
display: inline-flex 속성은 flex container를 인라인 블록 요소로 만드는 속성으로 display: flex 속성을 적용한 flex container는 블록 요소 입니다. 블록 요소는 브라우저 화면이 한 줄 전체를 차지하지만, 인라인 블록 요소는 한 줄의 일부 영역만 차지하게 됩니다.
flex container에 적용한 max-width: 100% 속성은 flex item인 텍스트 영역(.text 클래스)의 길이가 유동적으로 변할 수 있게 합니다. 그래서 텍스트가 아이콘을 제외한 나머지 공간을 가득 채우게 되고 텍스트 영역이 줄어들 때 나타나는 줄임표는 text-overflow: ellipsis 속성으로 구현합니다.
레이아웃 9 - 위아래로 흐르는 목록
위아래로 흐르는 목록은 자식 요소를 위아래로 먼저 정렬하고 자식 요소가 부모 요소를 벗어나면 줄을 바꿔 다시 위아래로 정렬하는 레이아웃 입니다.
다음은 위아래로 흐르는 목록의 기본 정렬 방식을 나타낸 그림입니다.
위아래로 흐르는 목록 구현하는 기본 CSS는 다음과 같습니다. flex container(.flex_container 클래스)에 필요한 속성을 적용합니다. 구현 예제는 CodePen 사이트의 "9. 상하 정렬 롤링 리스트"에서 확인할 수 있습니다.
.flex_container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: space-around;
align-content: space-around;
}
flex-direction: column 속성으로 위아래로 흐르게 하기
flex container에 적용하는 flex-direction 속성의 기본값은 row 입니다. flex-direction: row 속성은 flexbox의 콘텐츠가 좌우로 흐르게 합니다. 콘텐츠를 위아래로 흐르게 하려면 flex-direction 속성의 값을 column으로 설정합니다.
flex-wrap: wrap 속성으로 줄 바꾸기
flex-wrap은 flex item이 flex container를 벗어났을 때 줄을 바꾸는 속성으로 white-space 속성과 동일하게 작동합니다. 속성의 기본값인 nowrap은 flex item의 전체 크기가 flex container보다 커져도 줄을 바꾸지 않고 한 줄로 flex item을 배치합니다.
위아래로 흐르는 목록을 구현하려면 wrap을 flex-wrap의 속성값으로 사용합니다. flex-wrap: wrap 속성은 flex item의 전체 크기가 flex container보다 크면 줄을 바꿔 여러 줄로 flex item을 배치합니다.
flex-direction 속성과 flex-wrap 속성을 다음과 같이 flex-flow 속성으로 단축해 사용할 수도 있습니다.
.flex_container {
display: flex;
flex-flow: column wrap;
...
}
justify-content: space-around 속성과 align-content: space-around 속성으로 항목을 균등한 간격으로 정렬
align-content 속성은 flex item이 여러 줄로 나열되어 있을 때 주축을 기준으로 수직 정렬 방법을 설정하는 속성입니다. align-content 속성에 사용할 수 있는 속성값은 다음과 같습니다. justify-content 속성에 관해서는 "레이아웃 4 - 정렬이 다른 메뉴"를 참고합니다.
- stretch(기본값): flex item의 높이를 늘려 flex container의 전체 높이를 채움.
- flex-start: 교차축의 시작 부분을 기준으로 정렬.
- center: 교차축의 중앙을 기준으로 정렬.
- flex-end: 교차축의 끝부분을 기준으로 정렬.
- space-around: 교차축을 기준으로 flex-item을 일정한 간격으로 정렬.
- space-between: 첫 번째와 마지막 flex item은 교차축의 시작 부분과 끝부분에 정렬하고 나머지 flex item을 일정한 간격으로 정렬.
align-items 속성
align-content 속성과 비슷한 속성인 align-items 속성은 flex item이 한 줄로 나열되어 있을 때 주축을 기준으로 수직 정렬 방법을 설정하는 속성으로 align-items 속성에 관해서는 "레이아웃 5 - 폼 레이블 수직 중앙 정렬"을 참고합니다.
이때 주의해야 할 부분은 flex-direction: column 속성으로 주축의 방향이 전환되었기 때문에 정렬 기준도 전환된다는 점으로 수평 정렬의 기준은 align-content 속성으로 설정하고, 수직 정렬의 기준은 justify-content 속성으로 설정해야 합니다.
레이아웃 10 - 가로세로 비율을 유지하는 반응형 박스
브라우저의 크기에 따라 박스의 가로세로 크기가 동일한 비율로 늘어나거나 줄어드는 반응형 레이아웃 입니다.
가로세로 비율을 유지하는 반응형 박스를 구현하는 기본 CSS는 다음과 같습니다. 구현 예제는 CodePen 사이트의 "10. 가로세로 비율을 유지하는 반응형 박스"에서 확인할 수 있습니다.
.flex_container {
display: flex;
flex-wrap: wrap;
}
.flex_item_list {
flex-basis: 33.3%;
display: flex;
flex-direction: column;
}
.flex_item_image {
flex: auto;
/*
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
*/
}
목록을 이루는 항목 요소(.flex_item_list 클래스)에 display: flex 속성을 적용해 항목 요소가 이미지 박스 요소(.flex_item_image 클래스)의 flex container가 되게 합니다.
flex-basis: 33.3% 속성으로 자식 요소의 비율 고정
목록을 이루는 항목 요소가 일정한 비율로 유지되게 flex-basis: 33.33% 속성을 적용합니다.
flex: auto 속성으로 반응형 이미지 박스 만들기
이미지 박스는 유동적으로 반응할 수 있도록 flex: auto 속성을 적용합니다.
flex: auto 속성은 flex: 1 1 auto 속성과 같습니다. flex container의 크기가 커지면 flex item의 크기도 커지고, flex container의 크기가 작아지면 flex item의 크기도 작아집니다. flex container의 크기에 영향을 받는 반응형 flex item을 만들고 싶다면 flex: auto 속성을 사용합니다.
마치며
flexbox 레이아웃은 다음과 같은 장점이 있습니다.
- 구조가 간단하고 직관적이다.
- 반응형 레이아웃에 효과적이다.
- 협업자의 편의성을 높여준다.
CSS로 해결되는 부분이 많아 개발자는 스크립트 작업을 최소화할 수 있고, HTML 코드도 간략하게 작성할 수 있습니다. 디자이너는 반응형 관련 작업을 최소화할 수 있고, 더 다양하고 새로운 UI를 시도할 수 있습니다.
flexbox를 사용하면, 초보자는 보다 쉽게 레이아웃을 구현할 수 있고 전문가는 불가능했던 레이아웃을 구현할 수 있습니다.
출처 :
- https://studiomeal.com/archives/197
- https://d2.naver.com/helloworld/8540176
- https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox
'IT > HTML & CSS' 카테고리의 다른 글
SASS(SCSS)를 이용하여 margin / padding 을 조절할 수 있는 class 자동생성하기 (0) | 2022.02.18 |
---|---|
이번에야 말로 CSS Grid 배우기 (2) | 2022.02.17 |
웹 폰트(Web Font) 최적화 하기 (4) | 2022.01.18 |
아이폰(ios)에서 모멘텀(momentum) 스크롤 사용하기 (0) | 2021.12.22 |
CSS를 이용한 테마 컬러 변경 적용하기(feat.다크 모드) (0) | 2021.11.22 |
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)