부모 요소엔 Flexbox 속성을 잘 적용하지만 자식 요소에 적용할 수 있는 Flexbox 속성은 익숙치 않아서 정리해보았다.

💬 자식 요소에 적용해야 하는 Flexbox 속성

부모 요소에 적용해야 하는 속성들이 자식 요소들의 정렬과 관련이 있었다면, 자식 요소에게 적용해야 하는 속성인 flex 는 요소가 차지하는 공간과 관련이 있다.

flex 속성의 값

: flex 속성에는 세 가지 값을 지정해줄 수 있다.

1
flex: <grow(팽창 지수) > <shrink(수축 지수) > <basis(기본 크기) >;

grow(팽창 지수) 👉🏻 요소의 크기가 늘어나야 할 때 얼마나 늘어날 것인지

shrink(수축 지수) 👉🏻 요소의 크기가 줄어들어야 할 때 얼마나 줄어들 것인지

basis(기본 크기) 👉🏻 늘어나고 줄어드는 것과 상관없이 요소의 기본 크기는 얼마인지

🙋🏻‍♀️ 자식 요소에 flex 속성을 따로 설정해주지 않으면?

: 기본값이 적용되며, 왼쪽에서부터 오른쪽으로 콘텐츠의 크기만큼 배치된다.

1
flex: 0 1 auto; //flex: grow shrink basis

flex 속성 안에 세 가지 값을 한 번에 설정해줄 필요 없이, 다음과 같이 각 값을 따로 지정해줄 수 있다.

1
2
3
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;

💬 grow : 자식 박스는 얼마나 늘어날 수 있을까?

grow(팽창 지수) 는 요소의 크기가 늘어나야 할 때 얼마나 늘어날 것인지를 의미한다고 했다.

어떤 의미인지 알아보기 위해서 챕터 2-1에서 사용했던 HTML에서 자식 <div> 요소들에 id를 추가해서 grow값을 변경하며 변화를 확인해보자.

1
2
3
4
5
<main>
<div id="box1" class="box">box1</div>
<div id="box2" class="box">box2</div>
<div id="box3" class="box">box3</div>
</main>

flex 속성을 설정하기 전의 모습

230216-01.png

👉🏻 grow의 기본 값인 0은 빈 공간이 있어도 늘어나지 않음을 의미한다.

따라서 빈 공간이 있음에도 박스들이 늘어나지 않는다.

🙋🏻‍♂️ box1만 flex-grow : 1로 설정하면?

230216-02.png

🙋🏻‍♀️ box2도 flex-grow : 1로 설정하면?

230216-03.png

🙋🏻‍♀️ box3도 flex-grow : 1로 설정하면?

230216-04.png

grow(팽창 지수)는 정렬축 방향으로 빈 공간이 있을 때,

각 자식 요소들이 얼마나 늘어나서 남는 공간을 차지할 것인지 비율을 정하는 것

💬 shrink : 자식 박스는 얼마나 줄어들 수 있을까?

shrink(수축 지수)는 grow와 반대로, 설정한 비율만큼 박스 크기가 작아진다.

비율이 클수록 더 많이 줄어드는 것.

💡 flex-grow 속성과 flex-shrink 속성을 함께 사용하는 일은 추천하지 않는다.

비율로 레이아웃을 지정할 경우 flex-grow 속성 또는 flex: <grow> 1 auto와 같이 grow 속성에 변화를 주는 방식을 권장한다.
flex-shrink 속성은 width 나 이후 설명할 flex-basis 속성에 따른 비율이므로 실제 크기를 예측하기가 어렵기 때문이다. flex-grow 속성으로 비율을 변경하는 경우, flex-shrink 속성은 기본값인 1로 두어도 무방하다.

💬 basis : 이 박스의 기본 크기는 얼마일까?

basis(기본 크기)는 자식 박스가 flex-growflex-shrink 에 의해 늘어나거나 줄어들기 전에 가지는 기본 크기이다.

flex-grow가 0일 때, basis 크기를 지정하면 그 크기는 유지된다.

🙋🏻‍♀️ grow 는 0 : 1 : 1 로 설정하고, box1에 flex-basis : 50px 로 설정하면?

: box1의 크기가 늘어나거나 줄어들지 않고 50픽셀을 유지한다.

💬 세 개의 박스 모두 flex-grow : 1 일 때, 위 예시는 flex-basis : auto, 아래 예시는 flex-basis : 0 으로 설정하였다. 두 예시 중 실제로 1 : 1 : 1 의 너비를 갖는 것은 어느 예시인가?

230216-05.png

👉🏻 flex-basis:0으로 설정한 예시가 실제로 1 : 1 : 1의 너비를 갖는다.

🙋🏻 왜 이런 차이가 발생할까?

: flex-basis를 auto로 지정된 경우 컨텐츠 사이즈에 맞춰서 나타나기 때문이다.

flex-grow 속성의 값이 0인 경우에만 flex-basis 속성의 값이 유지된다.

: diplay 속성에 flex 가 적용된 컨테이너 내부에 존재하는 자식 박스는 경우에 따라, basis 로 설정된 크기가 항상 유지되는 것은 아니다. flex-grow 속성의 값이 양수일 경우, 늘어나면서 flex-basis 속성에 적용한 값보다 커질 수도 있다.

  • widthflex-basis를 동시에 적용하는 경우, flex-basis가 우선된다.
  • 콘텐츠가 많아 자식 박스가 넘치는 경우, width가 정확한 크기를 보장하지 않는다.
  • (flex-basis를 사용하지 않는다면) 콘텐츠가 많아 자식 박스가 넘치는 경우를 대비해, width 대신 max-width를 쓸 수 있다.

💬 Flexbox를 이용해 레이아웃 만들어보기

230216-06.png

  • index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <!DOCTYPE html>
    <html lang="ko-KR">
    <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="index.css" />
    </head>
    <body>
    <main>
    <section class="column1">
    <div class="icon">아이콘1</div>
    <div class="icon">아이콘2</div>
    <div class="icon">아이콘3</div>
    </section>
    <section class="column2">
    <div class="area">영역1</div>
    <div class="area">영역2</div>
    <div class="area">영역3</div>
    </section>
    <section class="column3">
    <div class="area">영역4</div>
    <div class="area">영역5</div>
    </section>
    </main>
    </body>
    </html>
  • index.css

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    :root {
    font-size: 30px;
    }

    * {
    box-sizing: border-box;
    }

    body {
    width: 100vw;
    height: 100vh;
    }
    main {
    width: 100%;
    height: 100%;
    display: flex;
    gap: 5px;
    }

    section {
    border: 1px solid red;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0.5rem;
    }

    .column1 {
    flex-grow: 1;
    }

    .column2,
    .column3 {
    align-items: stretch;
    gap: 10px;
    }

    .column2 {
    flex-grow: 4;
    }

    .column3 {
    flex: 12;
    }

    .icon {
    border: 1px dotted red;
    width: 2rem;
    margin-bottom: 10px;
    }

    .area {
    flex-grow: 1;
    border: 1px dotted blue;
    width: 100%;
    }