HTML, CSS, WEB 기술

FlexBox 로 구현하는 모던 CSS

Developer88 2024. 9. 17. 00:01
반응형

테이블이나,float, position등을 이용한 CSS는,

디자이너들의 복잡한 요구사항을 구현하는데 많은 어려움이 있었습니다.

반응형이 기본이 되어버린 시대에,

점점 더 구현이 어려워지게 되었는데요.

 

이러한 문제들을 해결하기 위한 방법으로,

Flexbox가 등장하였고,

2017년경부터는 대부분의 브라우저에서 지원을 하고 있습니다.

오늘은 이 Flexbox에 대해서 정리해 보도록 하겠습니다.

 

1. FlexBox

FlexBox는 반응형 웹 디자인을 구현하거나, 복잡한 레이아웃을 간단하게 만드는 데 매우 유용한데요.

컨테이너가 그 자식 요소들(flex items)의 크기와 순서를,

동적으로 조정해 줄 수 있기 때문입니다.

 

블럭요소나 inline요소를 이용해 css를 구성하는 경우가 많은데요.

하지만 flex로 모든 것을 구성할수 있습니다.

 

Flexbox를 시작할 때는,

부모요소의 display요소를 아래와 같이 'flex'로 선언을 하여 시작해주면 됩니다.

 

div { 
  display: flex;
}

 

 

2. MainAxis(주축)과 Cross Axis(교차축)

flex를 사용할 때 먼저 알아두어야 할 것이,

이 박스에서는 기준으로,

Main Axis(주축)과 Cross Axis(교차축)이 존재한다는 것 입니다.

이 둘을 비교하면 다음과 같습니다.

 

구분 주축(Main Axis) 교차축(Cross Axis)
의미 Flex 아이템들이 배치되는 기본 방향.

flex-direction에 의해 결정
주축으로부터 수직인 방향(교차되는 방향)

 

 

flex box에서는 자식 아이템들이 배치되는 방향을 'flex-direction'속성을 이용해 결정할 수 있는데요.

이를 통해 다양한 디바이스와 화면 방향에 맞는 유연한 UI를 제공할 수 있습니다.

flex-direction 속성은 다음과 같이 여러값으로 설정할 수 있습니다.

  • flex-direction: 아이템들이 배치되는 방향을 결정합니다
    • row: 기본값. 왼쪽에서 오른쪽으로 수평 배치.
      (주축의 방향이 텍스트의 방향과 동일하게 '→' 로 설정됨)
    • row-reverse: 텍스트의 반대 방향인 오른쪽에서 왼쪽으로(←) 수평 배치됩니다.
      • 원래 HTML에서 정의한 것의 역방향으로 오른쪽에서 왼쪽으로 쌓임
    • column: 아이템들이 위에서 아래로 배치(↓)
    • column-reverse: 요소들을 수직의 반대방향으로 아래에서 위로 배치(↑)
      • 원래 HTML에서 정의한 것의 역방향으로 아래에서 위로 쌓임

주의해야 할 점은,

reverse를 사용할 경우, 그 배치되는 방향이 바뀌므로,

justify-content에서 정의했던 정렬도 수정이 필요해질 수 있습니다.

 

 

3. 정렬

3-1. Justify-content와 align-items

flex box 의 아이템들을 정렬할 때는, 아래 2가지를 이용합니다.

둘의 차이점은 다음과 같습니다.

  • justify-content: Main Axis(주축)을 중심을 어떻게 요소들을 정렬할 것인지 결정
  • align-items: Cross Axis(교차축)을 중심으로 어떻게 배치할 것인지 결정

복잡하겠지만, 

우선은 justify-content는 flex-direction에 따른 Main axis를 따라 요소를 어떻게 정렬할 것인지를,

align-items는 flex-direct에 수직으로 교차하는 중심축을 따라 어떻게 배치할 것인지를 결정하는 것입니다.

 

구체적으로는 다음과 같이 설정을 할 수 있습니다.

  • justify-content: Main Axis(주축)을 따라서 아이템들의 배치 방법을 결정
    • flext-start: flex 컨테이너의 시작점부터 배치
    • flex-end: 컨테이너의 끝쪽으로 그루핑해서 배치.
    • center: Main Axis(주축)의 가운데로 그루핑해서 요소들을 정렬
    • space-between: 동일한 간격으로 요소들 사이를 비워둠
    • space-around: 요소들 주위를 동일 동일한 간격으로 함
  • align-items: Cross Axis(교차축)을 따라서 아이템들의 배치 방법을 결정
    • flex-start: 교차축의 시작점부터 배치
    • flex-end: 교차축의 끝에서부터 배치
    • center: 교차축을 따라서, 교차축의 가운데로 정렬
    • baseline: 요소들을 flex 컨테이너의 시작위치로 정렬
    • stretch: 기본 값. 요소들을 컨테이너에 맞춰서 늘림

 

 

3-2. align-self

align-items에서 받은 설정을 이어받지만,

아이템 하나에만, 다른 값을 주려고 할 때는,

'align-self'를 사용할 수 있습니다.

  • align-self: center; 
  • align-self: start; 
  • align-self: end; 

 

3-3. 게임을 통학 습득

flexbox의 정렬방법은,

종류도 많고 복잡해 보여서, 

하나씩 외우는 것보다는,

직접 적용해보면서 익히는 것이 가장 좋습니다.

 

다행히도 이런 것들을 해볼 게임들이 정말 많이 나와있는데요.

구글에 "flexbox game"을 검색해보면 많은 게임들을 볼 수 있는데요.

그 중 많이 나오는 것이 "Flexbox Froggy"입니다.

이런 것들을 자주 해보면서 익히면 많은 도움이 됩니다.

 

잊어먹을만 하면,

위에서 정리한 내용을 한번 훑어본다음,

게임을 해보는 것도 방법입니다.

 

4. 생각의 순서

flex-box를 배치하려 할 때는,

아래와 같은 순서로 생각하면 도움이 됩니다.

  1. 부모요소에 display: flex;를 선언
  2. flex-direction:주축이 가로인가 세로인가, 역배열(reverse)인가 아닌가?
    • 결국 시작은 어디를 축으로 하느냐입니다.
    • Row(가로배열)인가 Column(세로배열인가)를 정하는 것이 먼저.
    • 역배열을 사용해야 할 경우가 많지는 않으므로,
      가로인가 세로인가만 생각해도 대부분의 문제가 풀립니다.
  3. justify-content를 사용할 것인가, align-items를 사용할 것인가를 결정
    • 혹은 둘을 동시에 사용해야 하는지
    • justify-content: 주축을 기준으로 어떻게 배치하나? 
      • 처음, 끝, 가운데? 그것도 아니면 전체를 차지하고 요소들간 혹은 주변과의 간격을 기준으로 할까?
      • 이 부분이 사실상 가장 중요함
      • 참고로 flex-direction이 역방향일 경우에는, justify-content도 역으로 생각해야 합니다.
    • align-items: 교차축을 기준으로 어떻게 배치하나?
      • 가로라면, 세로에서 위, 아래, 가운데 등을 설정하는 것
      • 교차축으로 배치한 아이템들 중 하나에만 다르게 설정을 하고 싶다면, align-self를 사용

 

 

한가지 주의할 점은,

모든 시작은 부모의 속성에, display: flex; 선언하는 것 부터라는 사실입니다.

부모가 flex속성이 선언되지 않았는데,

다른 속성을 아무리 만져도 제대로 적용되지 않습니다.

 

이러한 순서로 기본적인 배치를 정하고 나서,

아래의 사항들 중 필요한 속성을 적용해 주면 됩니다.

 

4. order

특정한 아이템에 대해서 순서를 강제로 적용할 수 있습니다.

flex box의 아이템들은 0을 order의 기본값으로 가지고 있는데요.

이 order값의 순서대로 아이템들이 나열됩니다.

예를 들어서, 어느 하나를 -1로 설정해 준다면,

해당 아이템은 가장 앞에 나오게 되는데요.

그 다음 아이템을 더 앞에 두고 싶다면, 

-2로 설정해 주면 되겠지요.

아래는 circle이라는 아이템을 가진 요소를 2번째로 지정하였습니다.

 

.text { display: flex; }
#mybox {
  order:2;
}

 

아래에서는 mybox 아이디를 가진 요소만,

혼자 (교차축의)끝부분으로 보내었구요.

 

.test {
  display: flex;
  align-items: flex-start;
}

#mybox {
  align-self: flex-end;
  order: 8;
}

 

추가적으로, 주축인 가로축에서 아이템들의 끝부분에 위치시키기 위해,

order는 8로 주었습니다.

 

5. flex-wrap 과 align-content

5-1. flex-wrap

flex-wrap은 아이템들이 매우 많아서,

할 줄안에 표현되지 못할 정도일테 사용합니다.

 

이 속성을 이용하면,

요소들을 무조건 한줄안에 정렬할지(nowrap),

넘칠경우 여러줄에 걸쳐 정렬할지(wrap)를 결정할 수 있습니다.

  • flex-wrap속성
    • nowrap: 모든 요소를 한줄에서 넘치지 않게 함.
    • wrap: 요소들을 여러줄로 배치
    • wrap-reverse: 요소들을 여러줄에 배치하되, 반대로 정렬함

 

#test {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

 

 

5-2. align-content

이 쯤되면, 왜 이렇게 설정이 많은 것 일까하는 생각이 들기도 합니다.

align-content는 align-items하고는 어떻게 다른 것일까요?


align-items가 교차축에 대한 아이템들의 정렬방법을 정의했었는데요.

align-content는,

flex-wrap을 해서 여러줄로 배치된 아이템들에 대해서,

어떻게 배치할지에 대한 방법을 정의합니다.

 

한 마디로,

여러 줄로 배치된 경우(wrap),

어떻게 배치할 것인가에 대한 속성입니다.

  • flext-start: 시작점부터 배치
  • flex-end: 컨테이너의 끝쪽으로 그루핑해서 배치.
  • center: Cross Axis(교차축)의 가운데로 그루핑해서 요소들을 정렬
  • space-between: 동일한 간격으로 요소들 사이를 비워둠
  • space-around: 요소들 주위를 동일 동일한 간격으로 함
  • stretch: 여러줄들을 컨테이너 전체에 맞도록 늘려서 배치

 

아래는, wrap으로 아이템들이 여러줄로 표현될 경우,

교차축(세로)의 위에서부터 배치하도록 한 것 입니다.

 

#test {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-content: flex-start;
}

 

 

9. flex-flow

flex-flow는 flex-direction과 flex-wrap을 한번에 지정해 줄 수 있습니다.

둘의 속성을 한번에 지정할 경우가 많으므로, 

flex-flow로 direction과 wrap을 한번에 지정하면 효율적이겠지요.

 

아래는 'flex-direction: column;'과 'flex-wrap: wrap;'을,

flex-flow로 한줄로 줄인 것 입니다.

 

#test {
  display: flex;
  flex-flow: column wrap;
}

 

10. flex-grow vs flex-shrink

10-1. flex-grow vs flex-shrink 

flex-grow와 flex-shrink는,

flex 아이템들이 다양한 화면 크기와 컨테이너 조건에 대응하는 방식을 결정합니다.

둘은 다음과 같은 차이점이 있습니다.

 

속성 내용 기본 값
flex-grow 컨테이너 내 추가 공간이 있을 때 아이템이 차지할 수 있는 공간의 양. 
값이 클수록 더 많은 공간을 차지합니다.

공간이 남을때,
값이 커질수록 더 큰 비율로 공간을 차지합니다.
0
flex-shrink 컨테이너 내 공간이 부족할 때 아이템이 줄어들 수 있는 비율.
값이 클수록 아이템이 더 많이 줄어듭니다.

공간이 적을수록,
이 비율이 높은 요소가 더 큰 비율로 적어집니다.
1

 

 

이를 응용해서,

header, main, footer를 쉽게 잡아줄 수 있습니다.

아래와 같이 구성해 준다면,

화면을 늘릴경우, 

main화면이 화면 전체를 차지할 수 있게 됩니다.

 

  • header
    • height: 120px;
  • main
    • flex-grow: 1
  • footer
    • height: 120px;

header와 footer의 flex-grow값은 0으로 해 주어야 하는데요.

기본값이라 쓸필요 없습니다.

flexbox를 이용하면, main에 flex-grow:1을 주는 것 만으로도,

쉽게 main만 확장되는 레이아웃이 구현되는 것 입니다.

 

복잡한 케이스들을 생각하면서 외우기보다는,

이렇게 쉽게 적용할 수 있는 케이스들을 기준으로 생각하면서,

적용해가면 됩니다.

 

10-2. 가로로 적용해보는 경우

어디가 가변적이어야 하는지 기준을 잡으면 쉬운데요.

 

가운데 부분은 가변적이고,

좌우는 비율이 유지되어야 한다면,

아래와 같이 해 주면 됩니다.

  • right
    • flex-shrink:0
  • center
  • left
    • flex-shrink:0

center의 flex-shrink의 값은 1로,

기본값이라 쓸 필요 없습니다.

 

11. flex-basis

flex-basis는,

flex컨테이너 자식아이템의,

기본 크기(공간)를 정의해 줍니다.

flex-direction이 row이면 가로 너비가 될 것이고,

flex-direction이 column이라면 세로 높이가 됩니다.


width나 height는 고정된 크기를 지정하지만,
flex-basis는 시작점을 제공하되, 

유연하게 조절될 수 있습니다.

 

  • flex-basis: auto: 콘텐츠의 크기에 따라 상자의 크기가 결정됩니다.
  • flex-basis: 100px: 상자의 초기 크기를 100px로 설정
    • 우선은 100px로 설정하는 것
  • flex-basis: 0:  상자의 초기 크기를 무시하고, flex-grow와 flex-shrink에 따라 크기를 조절합니다.

 

 

12. 팁

12-1. flex:1 의 의미

flex: 1은 Flexbox 레이아웃에서 사용되는 속성으로, 

다음 세 가지 Flexbox 속성의 축약형입니다. 

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%
    • 요소의 초기 크기가 0
    • 요소의 콘텐츠 크기가 무시되며,
    • 위의 flex-grow와 flex-shrink에 따라 크기가 결정됨

한 요소가 나머지 공간을 모두 차지하게 하고 싶을 때 사용되는데요.

head, main, footer가 있을 때,

main에 flex:1속성을 주면 되겠지요.

728x90