가치투자자

[CSS] Flexbox 레이아웃 본문

Programming/HTML, CSS

[CSS] Flexbox 레이아웃

미주민 2023. 4. 17. 22:49
728x90
반응형

 Flex (플렉스) 

프론트엔드가 되기 위해선 레이아웃 배치를 잘 구현할 수 있어야 한다. 어떻게 요소들을 배치, 정렬하느냐에 따라 사용자가 보는 UI의 직관적인 느낌과 기능의 효율성이 달라지기 때문에 레이아웃 방식에 대해 제대로 공부해둘 필요가 있다.

 

 1. Flex란? 

이전에는 float나 inline-block 등을 이용해 레이아웃을 만들었지만, UI를 구성할 요소들의 사이즈가 불명확하거나 화면이 동적으로 변할 때도 유연하게 대응할 수 있는 기능을 제공하는 레이아웃 방식이 Flex다

Flex는  Flexible Box  또는  Flexbox 라고 불리기도 한다.

 

1-1. 부모 요소 flex container와 자식 요소 flex item

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>

 

Flexbox 레이아웃은  flex item 이라 불리는 자식 요소와 자식 요소들을 감싸고 있는 부모 요소인  flex container 로 구성되어 있다. flex container에서는 전체적인 정렬을 어떻게 할 것인지 속성을 부여해주고, flex item에서는 자식 요소의 크기나 순서에 관한 속성을 부여해준다.

 

위 코드를 아래처럼 구현하면, item이라는 클래스명을 가진 div 요소들은 flex item이며, container이라는 클래스명의 div 태그는 이 flex item들을 감싸는 flex container들이다.

 

1-2. 지원 범위

Can I use 사이트에 찾아보면, 크롬과 Safari는 최신 버전에서 완벽하게 지원하고 있으며, Internet Explorer(IE)은 10과 11버전에서 부분적으로 기능을 지원하기에 PC에서는 일부 버그가 발견되기도 한다. 그러나 버그는 너무 걱정하지 않아도 된다. Flexbox에 대해 충분히 이해하고 있다면, 극복할 수 있는 버그다. 모바일에서는 안드로이드 기반 크롬과 삼성 인터넷은 완벽하게 지원되며, IOS 기반 Safari와 안드로이드 브라우저에서는 최신 버전에서 완벽하게 지원하며, 과거 일부 버전에서 부분적으로 지원한다.

 

 


 2. 메인축(main-axis)과 교차축(cross-axis) 

flex를 좀 더 잘 이해하기 위해 알고 가야할 개념이 있다. 바로 메인축과 교차축이다.

메인축(main-axis)은 아이템이 정렬된 방향을 말하고, 메인축과 수직으로 교차하는 축을 교차축이라 한다.

 

 

728x90

 


 3. flex container 속성 

3-1. display: flex

.container {
  display: flex; /* or inline-flex */
}

 

flex 레이아웃을 구성하기 위해 적어줘야 하는 첫 코드다. flex를 적용하고 싶은 곳의 부모 요소(flex container)에 display: flex를 적용해주면 된다. 그래서 꼭 그 부모요소의 클래스명이 container가 아니어도 상관 없다.

다른 방향 설정이 없다면, flexbox의 아이템들은 기본적으로 가로 방향으로 배치가 된다. 그리고 각 아이템들의 width(가로) 길이만큼 왼쪽부터 차곡차곡 쌓이며, 아이템들의 height(높이)는 container의 height만큼 늘어난다.

 

 


3-2. flex-direction

부모 요소에 flex의 방향을 어떻게 설정해주냐에 따라 그 안에 있는 자식 요소들의 배치 방향이 정해진다.

아래의 사진을 보면, 네이버의 요소들도 서로 방향이 다르다. 메뉴(헤더)에 해당하는 부분들은 가로로 배치한 반면, 메인 페이지의 전반적인 방향은 세로로 배치되어 있다.

 

 

 

이처럼 flex의 메인축 방향은 크게 가로 또는 세로로 배치할 수 있다.

메인축이 가로 방향이면 row, 세로 방향이면 column이 된다.

1) 가로 방향 (기본값)

.container {
  flex-direction: row;
  /* display: flex만 해줘도 기본적으로 row가 적용되니 적지 않아도 row가 적용된다 */
}

2) 가로 역순 방향

.container {
  flex-direction: row-reverse;
}

3) 세로 방향

.container {
  flex-direction: column;
}

4) 세로 역순 방향

.container {
  flex-direction: column-reverse;
}

 

 


3-3. flex-wrap

만약 부모 요소의 width보다 자식 요소들의 width의 합이 더 클 때는 어떻게 될까?

만약 넘치게 된다면, nowrap처럼 튀어나오게 된다. UI상 보기 좋지 않은 배치다. 이 문제를 해결하기 위한 속성이 flex-wrap이다.

flex-wrap은 자식요소들을 여러줄로 묶어줌으로써 다음 줄에 튀어나온 자식 요소가 배치될 수 있도록 한다. 즉, 만약 튀어나오게 된다면 튀어나온 자식 요소를 줄을 바꿔 배치해줌으로써 깔끔한 UI를 만들 수 있다. 자식 요소가 계속해서 추가되는 경우에 사용하면 좋다.

 

1) 자식 요소들을 여러줄로 묶지 않음 (기본값)

.container {
  flex-wrap: nowrap;
}

2) 자식 요소들을 여러줄로 묶음

.container {
  flex-wrap: wrap;
}

3) 자식 요소들을 역방향으로 묶음 (기본값)

.container {
  flex-wrap: wrap-reverse;
}

 

 

만약 줄바꿈을 해주지 않고 한 줄에 자식 요소들을 쭉 나열하고 싶다면,  overflow: auto 를 추가해주면 스크롤이 생겨 부모 요소에서 튀어나오지 않는다.

.container {
  flex-wrap: nowrap;
  overflow: auto;
}

 


3-4. flex-flow

flex-direction과 flex-wrap을 동시에 적용할 수 있는 단축 속성이  flex-flow 다.

공백을 기준으로 flex-direction과 flex-wrap을 각각 적어주면 된다.

.container {
  flex-flow: row wrap;
}

/* 위가 아래의 단축 속성이다 */
.container {
  flex-direction: row;
  flex-wrap: wrap;
}

 


3-5. justify-content

이제 자식요소(아이템)들을 어떻게 정렬할지에 대해서도 알아야 한다.

 justify-content 메인축과 같은 방향으로 아이템들을 정렬하는 방식이다.

 

1) justify-content: flex-start (기본값)

시작점(flex-start)부터 배치. 방향이 row일 땐 왼쪽이 시작점이고, column일 땐 위가 시작점이다.

.container {
  justify-content: flex-start;
}

2) justify-content: flex-end

끝점(flex-end)부터 배치. 방향이 row일 땐 오른쪽이 끝점이고, column일 땐 아래가 끝점이다.

.container {
  justify-content: flex-end;
}

3) justify-content: center

아이템들을 메인축 방향 가운데 정렬

.container {
  justify-content: center;
}

4) justify-content: space-between

첫 번째 아이템은 시작점, 마지막 아이템은 끝점에 배치하고, 나머지 아이템들은 아이템 간의 간격이 고르게 정렬

.container {
  justify-content: space-between;
}

5) justify-content: space-around

각 아이템들의 주위(around)에 동일한 간격을 만들어 정렬해준다. 양 끝의 간격과 아이템 사이의 간격은 동일하지 않다.

.container {
  justify-content: space-around;
}

6) justify-content: space-evenly

각 아이템들 사이에 동일한 간격을 만들어 정렬해준다. 양 끝의 간격과 아이템 사이의 간격이 동일하다.

* IE와 Edge에서는 지원되지 않는 기능입니다.

.container {
  justify-content: space-evenly;
}

 


3-6. align-items

 align-items 는 교차축과 같은 방향으로 아이템들을 정렬하는 방식이다.

1) align-items: stretch (기본값)

부모 요소의 교차축 방향으로 끝까지 자식 요소를 늘려준다.

.container {
  align-items: stretch;
}

2) align-items: flex-start

교차축의 시작점부터 배치. 방향이 row일 땐 위쪽이 시작점이고, column일 땐 왼쪽이 시작점이다.

.container {
  align-items: flex-start;
}

3) align-items: flex-end

교차축의 끝점부터 배치. 방향이 row일 땐 아래쪽이 끝점이고, column일 땐 오른쪽이 끝점이다.

.container {
  align-items: flex-end;
}

4) align-items: center

아이템들을 교차축 방향 가운데 정렬

.container {
  align-items: center;
}

5) align-items: baseline

아이템들을 문자 기준선에 정렬

.container {
  align-items: baseline;
}

 


3-7. align-content

 align-content 는 교차축을 정렬하는 방식이다. align-content가 의미가 있는 결과를 만들어내려면 다음과 같은 조건을 갖추어야 한다.

  1. flex-wrap이 wrap으로 설정되어 있어야 한다.
  2. 아이템들의 줄이 1줄이 아니라 여러 줄일 때 의미가 있다.
.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 */
}

 

위 조건을 충족해야 의미가 있다는게 무슨 뜻인지 이해가 안 갈 수 있다.

이에 대해 이해하기 위해 align-items와의 차이를 설명하면서 함께 이야기해보겠다.

 

 align-items 는 교차축이 아니라, item들의 위치를 결정하는 것이다. 반면  align-content 교차축 자체의 위치를 설정하는 것이므로, 아래 사진처럼 서로 배치가 달라진다. 만약 1줄이었다면 두 속성의 차이를 알 수 없었을 것이다. 이를 통해 2줄 이상이 되었을 때 align-content를 사용해 전체적인 위치를 조정할 수 있다는 것을 알 수 있다.

 

 


3-8. 응용 (정중앙 배치)

위에서 알아본 justify-content와 align-items를 활용하면 이렇게 정중앙에 원하는 요소를 배치할 수 있다.

.container {
  justify-content: center;
  align-items: center;
}

 

반응형

 


 4. flex item 속성 

4-1. order

HTML 수정 없이 item의 순서를 지정할 수 있다. 작은 숫자일수록 먼저 배치가 되며, 음수도 허용된다.

.item:nth-child(1) {
  order: 3;          /* 1번째 자식요소를 3번째로 */
}
.item:nth-child(2) {
  order: 1;          /* 2번째 자식요소를 1번째로 */
}
.item:nth-child(3) {
  order: 2;          /* 3번째 자식요소를 2번째로 */
}

 


4-2. flex-basis 

 flex-basis 는 item의 기본 너비를 설정해준다.

기본값인 auto를 적어주면 각 아이템의 원래 width가 적용된다. 속성값으로 px, em, % 등을 사용할 수 있다.

content는 item의 내용물인 컨텐츠의 크기에 따라 너비가 결정된다.

flex-basis를 생략하면 flex-basis의 값은 0이 된다.

.item1 {
  flex-basis: auto;  /* 기본값 */
}
.item2 {
  flex-basis: 50%;
}
.item3 {
  flex-basis: content;
}

예시>

원래라면 1번째 item의 너비는 컨텐츠인 111만큼, 3번째 item의 너비는 3만큼이다.

그러나 item의 기본 너비를 100px로 설정해준 후에는 1번째와 3번째 아이템의 너비가 100px로 증가했고, 100px보다 큰 2번째 아이템은 원래 너비를 그대로 적용받는다.

<div class="container">
  <div class="item">111</div>
  <div class="item">2222222</div>
  <div class="item">3</div>
</div>
.item {
  flex-basis: 100px;
}

 


4-3. flex-grow

 flex-grow 는 item의 증가하는 너비 비율을 설정해준다. 기본값이 0이며, 숫자에 따라 각 item의 너비가 결정된다.

.num {
  flex-grow: 0  /* 기본값 */
}
.item {
  flex-grow: 1;
}

만약 첫 번째 요소는 1, 두 번째 요소는 2, 세 번째 요소는 1이면, 각 너비는 25%, 50%, 25%가 되는 것이다.

.item:nth-child(1) {
  flex-grow: 1;
}
.item:nth-child(2) {
  flex-grow: 2;
}
.item:nth-child(3) {
  flex-grow: 1;
}

 


4-4. flex-shrink

 flex-shrink 는 item의 감소하는 너비 비율을 설정해준다. 기본값이 1이며, 0보다 큰 숫자에 따라 각 item의 너비가 결정된다.

만약 줄어든 길이가 90px일 때, 첫 번째 요소가 2, 두 번째 요소가 1이면 첫 번째 요소는 60px, 2번째 요소는 30px 너비가 줄어들게 된다.

.item {
  flex-shrink: 1;  /* 기본값 */
}

 

shrink의 값이 0일때는 축소가 해제되어 원래 너비를 유지하게 된다.

.item:nth-child(1) {
  flex-shrink: 1;
}
.item:nth-child(2) {
  flex-shrink: 0;
}
.item:nth-child(3) {
  flex-shrink: 1;
}

 


4-5. flex

 flex 는 flex-grow, flex-shrink, flex-basis의 축약형 속성이다. 기본값은 각각 0 1 auto이다.
만약 flex: 1만 작성했다면, flex-grow의 값이 1이고 나머지는 기본값이 적용된다. 주의할 점은 flex-basis의 기본값은 auto지만, flex에서 flex-basis 값을 생략할 경우 auto가 아니라 0이 적용된다.

이러한 단축 속성인 flex가 간편할 수는 있지만, W3C에서는 이 단축 속성을 쓰는 것보다 각각 풀어서 쓰는 것을 추천하고 있다.

.item {
  flex: 1;
  /* flex-grow: 1; flex-shrink: 1; flex-basis: 0 */
}

 


4-6. align-self

 align-self 는 교차축에서 개별 item을 정렬하는 속성이다. align-items는 모든 item의 배치를 동시에 적용했다면, align-self는 필요에 따라 개별 item의 배치를 조정할 수 있다.

auto가 기본값으로, 상위 요소에 적용된 align-items의 값을 상속받아 온다. align-self의 속성은 align-items와 동일하며, align-self에 적용된 속성이 align-items의 속성보다 우선적으로 적용된다.

.container {
  display: flex;
  align-items: center;
}
.item {
  align-self: auto;  /* 기본값 */
  /* align-self: flex-start */
  /* align-self: flex-end */
  /* align-self: center */
  /* align-self: baseline */
}

예시>

다음 예시를 살펴보면, 부모 요소인 container에는 center로 적용되어 있지만, 3번째 요소의 flex-end가 우선적으로 적용된다.

.container {
  display: flex;
  align-items: center;
}
.item:nth-child(3) {
  align-self: flex-end;
}

 

align-self를 잘 활용하면 아래처럼 다양한 위치에 내가 원하는 요소를 배치할 수 있다.

 


</> 끊임없이 성장하기 위해 공부한 내용을 글로 작성하고 있습니다. 틀린 부분이나 추가해야 할 부분이 있다면 언제든 댓글로 남겨주세요❗️

 


References

 

 

728x90
반응형

'Programming > HTML, CSS' 카테고리의 다른 글

[HTML] 시멘틱 태그(semantic tag)란?  (2) 2023.06.17
[CSS] position  (0) 2023.06.04
[CSS] display  (0) 2023.06.03
[CSS] 선택자 : 가상 클래스 & 가상 요소  (0) 2023.04.21
[CSS] 선택자  (1) 2023.04.19