[검색] 공부하기/CSS

Flex

Ben의 프로그램 2023. 6. 28. 21:18
728x90

Flex 가 등장한 이유

  • mozila 재단에서 운영하는 문서에 따르면 Flexible Box, Flex Box 라고 불리는 Flex 는 1차원 레이아웃 배치를 위한 모델이라고 설명하고 있습니다. 

    여기서 말하는 1차원 레이아웃 이라는 말의 의미는 Grid 의 2차원 레이아웃과는 대조되는 개념입니다. 

    왜냐하면 Flex 는 row 혹은 column을 동시에 제어할 수 있는 Grid 와는 달리 주축을 중심으로한 제어의 기능을 수행하기 때문이라고 설명하고 있습니다. 

    아무튼 1차원 레이아웃 모델인 Flex 는 레이아웃 배치 전용 기능으로 개발되었는데, 그 이전에는 레이아웃을 만들 때 쓸 수 있는 기능이 마땅치 않았기 때문에 float 이나 inline-block 등을 이용한 방식을 보완하기 위한 목적이었습니다. 

Flex 가 사용 되는 구조 이해하기

  • 본격적으로 flex 에 대해서 공부하기 전에 flex 가 사용되는 기본적인 틀을 이해하고 넘아가겠습니다. 
    <div class="container">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
  • 우선 flex 가 사용되는 HTML 구조는 위와 같습니다. 

    부모 container 가 있으며 직계 자식들이 flex item 이 됩니다. 
  • flex 에서 사용되는 속성은 크게 2가지로 나뉘게 됩니다. 

    하나는 container 에 적용되는 속성들이고 하나는 item 들에 적용되는 속성들입니다. 

    크게 2가지 속성들이 flex 에 있다는 것을 알아두고 다음을 읽어가시면 될 것 같습니다. 

Flex 의 두 개의 축 (main axis & cross axis)

  • Flex 를 사용하기 위해서는 main axis 와 cross axis 라는 두 개의 축을 이해하고 있어야 합니다. 
  • main axis 는 flex-direction 속성을 활용하여 row & row-reverse 혹은 column & column-reverse 으로 설정할 수 있습니다. 

flex-direction : row 와 flex-direction : row-reverse 의 출력 모습
column 과 column-reverse 의 출력 모습

  • 여기서 주의 깊게 봐야 하는 점은 flex-direction 을 row 혹은 row-reverse 로 설정하면 main axis 가 row 를 기준이 된다는 것을 의미하기 때문에 자연스럽게 cross axis 는 column 을 기준으로 동작하게 됩니다. 

    반대로 flex-direction 이 column 혹은 column-reverse 라면 main axis 가 row 라는 것을 의미하기 때문에 cross axis 는 row 를 기준으로 동작하게 됩니다. 

Flex-direction 에 따라 달라지는 writing mode 

  • 영어 사용권자들은 글을 쓸 때 왼쪽 위에서 시작해서 오른쪽 아래에서 끝나게 됩니다. 

    하지만 Flex 는 다양한 글쓰기 방식을 지원하기 위해 flex-direction에 따라 시작 지점과 끝 지점이 달라지게 됩니다. 

    위에서 본 것처럼 row reverse 를 하면 오른쪽이 1번 순차적으로 왼쪽으로 갈수록 내용이 이어지게 되며 콘텐츠도 오른쪽에 딱 붙어서 출력되는 것을 확인할 수 있습니다. 

    마찬가지로 column 과 column reverse 에서도 writing mode 는 달리지게 됩니다. 

Flex Container & Flex Item & default setting

  • Flex box laid out(레이아웃)이 사용되는 지역을 Flex Container라고 부릅니다. 
  • Flex Container 를 생성하기 위해서는 container 의 display 속성을 flex 혹은 inline-flex 로 설정하면 됩니다. 
  • Flex Container 의 display 속성이 설정되면 container 의 직계 자식들은 그 즉시 flex item 으로 설정됩니다. 
  • 다른 모든 CSS 요소들이 그러하듯, flex item 으로 설정된 요소들에게도 그 즉시 적용되는 default 속성들이 있는데요. 다음과 같은 것들이 자동으로 설정되게 됩니다.  

    - flex-direction 속성의 default 값은 row 입니다. 
    - Flex item 들은 flex direction row 에 따라서 나열되게 됩니다. (inline 요소들처럼 붙어서 표현됨)
    - Flex item 들은 main axis 의  start edge 부터 순서대로 쌓이게 됩니다. 
    - Flex item 들은 main axis 방향으로 자동으로 stretch 하지 않습니다. (무슨 말이냐면 flex direction 이 row  일 때 container 의 width 가 300 px 이라면 해당 300 px 을 다 채우기 위해서 item 들의 컨텐츠 너비보다 더 크게 확장하지는 않는다는 말이다) 
    - Flex item 들은 main axis 방향으로 자동으로 shrink 합니다.
    - Flex item 들은 cross axis 방향으로 자동으로 stretch 합니다. 
    (무슨 말이냐면 flex direction 이 row 일 때, container 의 height 가 300 px 이라면 item 의 콘텐츠 height 가 300px 보다 작더라도 자동으로 늘어나서 채우게 된다는 말이다)
    - flex-basis 속성의 default 값은 auto 이다. 
    - flex-wrap 속성의 default 값은 nowrap 이다. 
  • 이런 기본 속성들이 의미하는 바는 다음과 같습니다.

    - flex item 들은 자동으로 row 에 차곡 차곡 쌓인다.
    - flex item 의 content 사이즈만큼만 main axis 를 차지합니다.
    - 만약 flex item 의 컨텐츠의 사이즈가 container 의 main axis 크기보다 크다면 wrap (밑 행으로 떨어져서 표기되는 것) 하지 않고 overflow (화면 오른쪽 바깥으로 나가서 보이지 않는 영역이 생긴다) 하게 됩니다. 
    - 만약 flex item 들 중에 cross axis 방면으로 크기가 더 큰 item 이 있다면 해당 item 의 cross axis 크기에 맞추어서 다른 item 들도 크기를 자동으로 stretch 합니다. 

Changing flex-direction

  • flex container 에게 flex-direction 속성과 해당하는 속성 값을 부여하는 방식으로 우리는 flex item 들이 어떻게 display(배치)될지 결정할 수 있습니다 

    예를 들어서 flex-direction 을 row-reverse 로 설정하면 start line 과 end line 이 바뀌게 되고 화면에 출력되는 모습도 완전히 달라지게 됩니다. 

Multi-line flex containers with flex-wrap

  • 우리가 지금까지 쓰고 보았던 flex 속성은 single line flex container 에 대한 내용들이었습니다.
    우리가 원한다면 flex item 들을 여러 줄에 걸쳐서 wrap(자동 줄바꿈?) 되도록 할 수 있습니다.

    다만, 이렇게 할 경우 각 line 들은 각각 새로운 flex container 가 생성되어 flex item 을 갖게 된다는 것을 꼭 알아두어야 합니다. 
  • wrapping 이 실행되도록 하기 위해서는 flex-wrap 속성을 wrap 속성 값으로 설정하면 됩니다.

    이렇게 하면 flex item 들이 한 줄(main axis)에 표현될 수 있는 것보다 커지게 될 때 다른 줄로 wrap 하게 됩니다.

  • 위 그림에서 item 들은 container 의 main axis 가 포함할 수 있는 크기보다 더 큰 크기를 갖고 있습니다. 따라서 우리가 flex-wrap 속성 값을 wrap 으로 설정하면 위와 같이 wrap 이 진행되는 것을 알 수 있습니다. 

    이 그림에서 다시 한번 이야기하지만, 각 line 은 독자적인 container 가 있다는 것을 알아두어야 합니다. 이 말인 즉슨 첫 line 에서 다 채우지 못한 공백은 다음 line 에서 채워넣거나 하는 등의 영향은 발생하지 않는다는 것입니다. 

    flex-nowrap 으로 설정하면(flex-wrap 의 default 값입니다), 초과 되는 부분은 부모 main axis 크기 너비에 맞추기 위해 shrink 하게 됩니다. 

    한편 nowrap 을 사용하는 경우에 만약 item 들이 shrink 되는 것이 금지되도록 설정되었거나 shrink 하더라도 부모 main axis 의 크기를 초과할 경우 overflow 가 발생할 수 있습니다. 

Flex flow Shorthand

  • Flex flow 속성을 활용하면 flex-direction 과 flex-wrap 을 한 번에 표기할 수 있습니다. 

    두 속성 값을 입력하는데, 두 값은 띄어쓰기로 구분하며 첫 번째 값은 flex-direction 을 의미하며 두 번째 값은 flex-wrap 값을 의미합니다. 
        #parent2 {
            flex-flow: row wrap;
        }
  • 위와 같이 표현할 수 있습니다. 

Properties applied to flex items (available space)

  • 이번에는 flex item 에 적용되는 속성들에 대해서 알아봅시다. 

    크게 3가지 속성이 있습니다. 

    flex-grow
    flex-shrink
    flex-basis 

    입니다.
  • flex item 에 적용되는 3가지 속성들을 자세히 알아보기 전에 먼저 이해해야 하는 개념이 있습니다.

    바로 available space(가용 가능 공간) 입니다. 

  • container 의 가용 가능한 전체 크기가 500 px 인데, item 들이 300 px 을 차지하고 있다면 available space 는 200px 입니다.

    available space 를 item 들이 어떻게 사용하게 하는지를 컨트롤 하는 것이 item property 3가지 입니다.

    이제 하나씩 차례대로 알아보겠습니다. 

The flex-basis property

  • flex-basis 속성은 해당 속성을 부여받은 item 이 main axis 에 대해서 기본적으로 가지게 될 최소 크기를 의미합니다.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
        }
        div {
            margin-top: 20px;
        }
        p {
            border: solid 1px;
            width: 300px;
            height: 100px;
        }
        .child1 {
            background-color: lavender;
            flex-basis: auto;
        }
        .child2 {
            background-color: darkgray;
            flex-basis: content;
        }
        .child3 {
            background-color: gold;
            flex-basis: 200px;
        }
        .parent {
            display: flex;
        }
        #parent1 {
            flex-direction: column;
        }
        #parent2 {
            flex-flow: row wrap;
        }
        #paren3 {
            flex-wrap: wrap;
        }
        #parent4 {
            border: 3px solid red;
            justify-content: center;
            flex-basis: auto;
        }
       
    </style>
</head>
<body>
    <h1>flex로 자식요소들 정렬하기</h1>
    <div class="parent" id="parent1">
        <p class="child1">child1</p>
        <p class="child2">child2</p>
        <p class="child3">child3</p>
    </div>
    <div class="parent" id="parent2">
        <p class="child1">child1</p>
        <p class="child2">child2</p>
        <p class="child3">child3</p>
    </div>
    <div class="parent" id="parent3">
        <p class="child1">child1</p>
        <p class="child2">child2</p>
        <p class="child3">child3</p>
        <p class="child1">child1</p>
        <p class="child2">child2</p>
        <p class="child3">child3</p>
    </div>
    <div class="parent" id="parent4">
        <p class="child1">child1</p>
        <p class="child2">child2</p>
        <p class="child3">child3</p>
    </div>
</body>
</html>
 
 
  • 위 예시를 보면 flex-direction 이 column 으로 되어 있는 parent1 의 경우 main axis 가 column 이기 때문에 세로 크기가 flex-basis 로 부여받은대로 표현된 것을 확인할 수 있습니다. 

    반면에 flex-direction 이 row 로 되어 있는 parent2 의 경우 main axis 가 row 이기 때문에 가로 크기가 flex-basis 에서 부여받은대로 표현된 것을 확인할 수 있습니다. 

The flex-grow property

  • flex-grow 속성은 flex item 들이 main axis 의 available space 를 차지할 수 있는 권한을 부여합니다. 

    무슨 말이냐면 

  • 위 그림으로 예를 들어 보겠습니다.

    만약 우리가 a item 에게 flex-grow: 1; 을 주게 된다면 a item 은 남은 available space 차지할 권한을 갖게 됩니다. 따라서 a item 은 300 px 을 차지하고 b, c 는 원래 차지하던 100 px 을 차제하게 됩니다.

    만약 우리가 a, b item 에게 flex-grow: 1; 을 주게 된다면 a, b item 은 남은 available space 를 균등하게 나누어 갖을 권한을 갖게 됩니다. a, b item 은 200 px 을 차지하게 되고 c는 원래 차지하던 100 px 을 차지하게 됩니다.

    그런데, 재미있는 점이 하나 있습니다. main axis 의 available space 를 차지할 비율을 우리가 임의로 지정해줄 수 있다는 점인데요. 

    a item 에게 flex-grow : 2 를 주고 b item 에게 flex-grow : 1 을 주게 되면 a 와 b item 은 2 : 1 비율로 available space 를 차지하게 됩니다. 

  • 위 그림은 child1 에게 flex-grow : 1 의 속성을 부여한 결과값입니다. main axis 의 available space를 child1 이 차지한 것을 알 수 있습니다. 

The flex-shrink property

  • flex-shrink 속성은 item 들의 크기가 container 의 main axis 의 크기보다 커졌을 때 크기를 줄여줄 권한을 부여합니다. 

    여기서 shrink 한다는 것은 flex-basis 가 정한 크기보다 줄어들 수 있다는 것을 의미합니다. 

    flex-grow 처럼 값을 임의로 부여할 수 있는데, flex-grow 와 같이 shrink 하는 비율을 우리가 임의로 지정할 수 있다는 것을 의미합니다. 

    flex-shrink 속성 값을 크게 부여받으면 더 다른 item 보다 더 빠른 속도로 shrink 하게 됩니다. 

Shorthand values for the flex properties (flex shorthand)

  • 앞서 container 의 속성들 빠르게 입력할 수 있었던 flex-flow 와 마찬가지로 item 들의 속성을 빠르게 입력할 수 있는 방법이 flex 입니다.

    flex 속기법은 3가지 값을 갖습니다.

    flex-grow
    flex-shrink
    flex-basis

    이렇게 3가지입니다.

  • 예를 들어 위와 같이 flex: 1 1 auto; 로 설정하면 flex-grow 1 , flex-shrink 1, flex-basis auto 로 설정하는 것과 같은 효과를 갖습니다. 

  • 한편, 이 flex shorthand 에는 predefined 된 속성값들이 있습니다. 

    flex: initial;

    initial 값은 flex item 들의 속성값을 초기 값으로 설정합니다. 즉 flex: 0 1 auto 로 설정한다는 의미입니다. 

    flex: none;

    none 값은 nonflexible 한 item 으로 만듭니다. 즉 flex: 0 0 auto 로 설정한다는 의미입니다. 

    flex: auto;

    auto 값은 모든 flex 를 설정한다는 의미입니다. 즉 flex: 1 1 auto 로 설정한다는 의미입니다. 

Alignment, justification and distribution of free space between items

  • Flexbox 의 가장 강력한 기능 중 하나는 바로 main axis 와 cross axis 를 기준으로하여 item 들을 align 하거나 justify 할 수 있다는 것입니다. 명심해야 하는 점은 flex item 들에 적용되는 속성들이므로 반드시 container 직계 부모를 가진 flex item 들에만 적용하여야 정상적으로 작동합니다. 

align-items

  • align-items 속성은 item 들을 cross axis 를 기준으로 정렬 시킵니다. 

    defualt 값은 stretch 입니다. (이 때문에 container 를 flex 로 설정하는 순간 cross axis 가 가장 큰 item 을 기준으로 다른 item 들도 같이 stretch 합니다)

    align-items 속성 값으로 사용되는 것들은 4가지가 있습니다.

    - stretch(default)

    - flex-start

    - flex-end

    - center

  • 유념해서 보아야 하는 것은 flex-start 와 flex-end, flex-center 로 설정을 하면 stretch 를 하지 않는다는 점입니다. 

justify-content

  • justify-content 속성은 main axis 를 기준으로 item 들을 정렬합니다.

    default 값은 flex-start 로 container 를 flex 로 설정하면 start line 에서 딱 붙어서 요소들이 붙는 이유입니다.

    justify-content 속성 값에는 align-items 에는 없는 속성 값들이 있습니다.

    space-between 속성 값은 start line 과 end line 에 요소 하나씩을 배치시킨 이후에 남은 공간들을 균등하게 배분하는 방식입니다. 

  • 위와 같이 표현됩니다. 

    space-evenly 는 start line 과 end line 에 요소를 배치하지 않고 요소들 사이 그리고 start & end 사이에 균등한 space 를 갖도록 합니다. 

  • 위와 같이 표현됩니다. 

    space-around 는 space evenly 와 비슷하지만 다른 점이 있는데, 각 요소 좌 우에 동일한 space 를 갖게 됩니다. 

  • 우와 같이 표현됩니다. (start line 과 one 요소간의 거리가 one 요소와 two 요소 간의 거리의 1/2 입니다)

 

 

Flex 포스팅을 읽느라 고생 많으셨습니다. 

ㅎㅎ 성공적으로 포스팅을 작성한 나 자신에게도 축하와 격려의 박수를 보냅니다. 

고생 많으셨고, Flex 를 충분히 이해하게 되었기를 바랍니다. 
참고 
: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox
: https://studiomeal.com/archives/197