Flexible box layout/Typical use cases

김동현·2026년 3월 21일

mdn 학습 번역 - CSS

목록 보기
97/190

안녕하세요! 오늘 다뤄볼 MDN 문서는 여태껏 우리가 배웠던 Flexbox의 강력한 기능들이 실제 웹사이트에서 어떻게 쓰이는지 보여주는 플렉스박스의 전형적인 사용 사례(Typical use cases of flexbox)입니다.

이 문서는 단순히 이론을 넘어, 네비게이션 바, 폼 컨트롤, 카드 레이아웃 등 프론트엔드 개발자라면 실무에서 매일 마주하게 될 UI 패턴들을 Flexbox로 어떻게 우아하게 해결하는지 보여줍니다. 앞으로 만드실 포트폴리오 프로젝트에도 그대로 가져다 쓸 수 있는 코드들이니 잘 눈여겨보시기 바랍니다!


플렉스박스의 전형적인 사용 사례 (Typical use cases of flexbox)

이 가이드에서는 플렉스박스(flexbox)의 흔한 사용 사례들, 즉 다른 레이아웃 방식보다 플렉스박스를 사용하는 것이 훨씬 더 합리적인 상황들을 살펴볼 것입니다.

이 문서에서 다룰 내용 (In this article)


왜 플렉스박스를 선택해야 할까요? (Why choose flexbox?)

플렉스박스는 여러분이 아이템들의 컬렉션을 1차원적(가로 한 줄, 혹은 세로 한 줄)으로 배치하고 싶거나 아이템 간의 간격(spacing)을 제어하고 싶을 때 일반적으로 가장 적합한 CSS 레이아웃 솔루션입니다. 이 가이드에서는 플렉스박스의 대표적인 사용 사례 몇 가지를 살펴보겠습니다.


네비게이션 (Navigation)

웹사이트의 상단 네비게이션은 일련의 아이템들을 가로 막대 형태로 표시하는 매우 흔한 패턴입니다. 이는 아마도 플렉스박스의 가장 흔한 예제이자, 이상적인 플렉스박스 사용 사례로 볼 수 있습니다.

가로로 표시하고자 하는 일련의 아이템들이 있을 때, 십중팔구 공간이 남게 됩니다. 우리는 이 남는 공간(additional space)을 어떻게 처리할지 결정해야 하는데, 두 가지 옵션이 있습니다. 남는 공간을 아이템들의 '바깥'에 분배하여 아이템들 사이나 주위에 여백을 두거나, 아니면 아이템들 자체가 늘어나게(grow) 해서 남는 공간을 아이템 '내부'로 흡수시키는 방법입니다.

공간을 아이템 바깥으로 분배하기 (Space distributed outside the items)

아이템 사이나 주위에 공간을 분배하기 위해 우리는 플렉스박스의 정렬 속성, 특히 justify-content 속성을 사용합니다. 이 속성에 대한 더 자세한 내용은 주축(main axis) 정렬을 다루는 플렉스 컨테이너 안에서 아이템 정렬하기에서 읽어보실 수 있습니다.

이 예제에서는 아이템들을 각자의 자연스러운 크기(콘텐츠 크기)로 표시하고, justify-content: space-between을 사용하여 아이템들 사이에 동일한 간격을 만듭니다. space-aroundspace-evenly 값을 사용하여 공간 분배 방식을 바꿀 수도 있습니다. 또한 start를 사용해 남는 공간을 아이템들 끝 쪽에 몰아넣거나, end로 아이템들 앞쪽에 공간을 두거나, center를 사용해 네비게이션 아이템들을 화면 정중앙에 모을 수도 있습니다.

<nav>
  <ul>
    <li><a href="#">Page 1</a></li>
    <li><a href="#">Page 2</a></li>
    <li><a href="#">Page 3 is longer</a></li>
    <li><a href="#">Page 4</a></li>
  </ul>
</nav>
nav {
  border: 2px solid #eeeeee;
}

nav a {
  text-decoration: none;
  color: black;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  padding: 10px;
  display: block;
}

nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: space-between; /* 아이템 사이의 공간을 동일하게 띄웁니다! */
}

공간을 아이템 내부로 분배하기 (Space distributed within the items)

네비게이션을 구성하는 또 다른 패턴은 아이템들 사이에 빈 공간을 만드는 대신, 남는 가용 공간(available space) 자체를 아이템 내부에 분배하여 아이템을 뚱뚱하게 늘리는 것입니다. 우리는 flex 속성을 통해 아이템들이 서로 일정한 비율로 늘어나거나 줄어들도록 만들 수 있습니다.

만약 여러분이 네비게이션 아이템들의 본래 콘텐츠 길이(size)를 존중하면서 남는 공간만 동일하게 나눠 가지길 원한다면, flex: auto를 사용할 수 있습니다. 이는 flex: 1 1 auto의 단축형으로, 모든 아이템이 flex-basis: auto(자신의 원래 콘텐츠 크기)에서 출발하여 남는 공간을 똑같이 나눠 받아 늘어나고 줄어든다는 것을 의미합니다. 이렇게 하면, 애초에 글자 수가 더 긴(크기가 큰) 아이템이 다른 아이템들과 동일한 양의 남는 공간을 받더라도 결과적으로 최종 크기는 더 길어지게 됩니다.

아래 라이브 예제에서 flex: autoflex: 1로 바꿔 보세요. flex: 1flex: 1 1 0의 단축형이므로, 모든 아이템이 flex-basis: 0에서 출발하게 됩니다. 따라서 콘텐츠의 원래 길이를 완전히 무시하고 전체 공간을 아주 똑같이 나눠 가져 모든 아이템의 너비가 완벽하게 같아지게 됩니다.

💡 강사의 실무 포트폴리오 팁!
"메뉴 버튼 길이를 글자 수와 상관없이 똑같이 맞춰주세요"라는 기획자의 요구사항이 들어오면 flex: 1을 주고, "글자가 긴 버튼은 자연스럽게 길게 놔두고 남는 여백만 적절히 채워주세요"라는 요구사항이 들어오면 flex: auto를 주면 됩니다!

<nav>
  <ul>
    <li><a href="#">Page 1</a></li>
    <li><a href="#">Page 2</a></li>
    <li><a href="#">Page 3 is longer</a></li>
    <li><a href="#">Page 4</a></li>
  </ul>
</nav>
nav {
  border: 2px solid #eeeeee;
}
nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
}

nav a {
  text-decoration: none;
  color: black;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  padding: 10px;
  display: block;
}

nav li {
  flex: auto; /* 혹은 flex: 1을 넣어 너비의 변화를 확인해보세요! */
}

분할 네비게이션 (Split navigation)

주축 상에서 아이템들을 정렬하는 또 다른 기막힌 방법은 바로 자동 마진(auto margins)을 사용하는 것입니다. 이 테크닉을 활용하면 네비게이션 바에서 한 그룹의 아이템들은 왼쪽으로 몰아두고, 다른 한 그룹(예: 로그인 버튼)은 오른쪽으로 뚝 떨어뜨려 놓는 디자인 패턴을 쉽게 구현할 수 있습니다.

아이템들은 기본적으로 normal(플렉스박스에서는 start로 동작)로 정렬되어 모두 왼쪽에 붙어 있습니다. 여기에 우리는 마지막 아이템(혹은 오른쪽으로 보내고 싶은 첫 번째 아이템)에 margin-left: auto; 값을 부여하여 오른쪽으로 쭈욱 밀어버립니다. HTML 코드에서 .push-right 클래스를 다른 <li> 항목으로 옮겨보면서 분할 지점이 어떻게 바뀌는지 테스트해 보세요.

<nav>
  <ul>
    <li><a href="#">Page 1</a></li>
    <li><a href="#">Page 2</a></li>
    <li><a href="#">Page 3 is longer</a></li>
    <li class="push-right"><a href="#">Page 4</a></li>
  </ul>
</nav>
nav {
  border: 2px solid #eeeeee;
}

nav a {
  text-decoration: none;
  color: black;
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  padding: 10px;
  display: block;
}

nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 20px;
}

.push-right {
  margin-left: auto; /* 핵심 코드! 나보다 왼쪽의 남는 공간을 다 차지하겠다! */
}

아이템 중앙 정렬하기 (Center item)

개발자들 사이의 오래된 농담 중 하나는 "웹 디자인에서 가장 어려운 문제는 수직 중앙 정렬이다"라는 것입니다. 하지만 아래 라이브 예제에서 볼 수 있듯이, 플렉스박스 정렬 속성을 사용하면 콘텐츠를 수직 중앙에 맞추는 것은 이제 식은 죽 먹기입니다.

<div class="box">
  <div></div>
</div>
.box {
  height: 300px;
  border: 2px dotted rgb(96 139 168);
  display: flex;
  align-items: center; /* 수직 중앙 정렬 */
  justify-content: center; /* 수평 중앙 정렬 */
}

.box div {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  width: 100px;
  height: 100px;
}

💡 부연 설명:
사실 부모에 display: flex;만 주고 justify-contentalign-items를 쓰지 않아도, 정렬하고 싶은 정중앙의 자식 요소에 margin: auto;를 주면 완벽하게 수평/수직 중앙 정렬이 일어납니다! Flexbox 안에서 margin: auto는 상하좌우 남는 여백을 모두 자신이 차지하려고 하기 때문에 결국 요소가 정중앙으로 밀리게 되는 원리입니다.


카드 형태의 컴포넌트 목록을 만들 때, 만약 카드마다 들어있는 글의 양(콘텐츠 양)이 서로 다르다면 어떻게 될까요? 부모를 Grid나 Flexbox로 묶어두면 카드 자체의 높이는 옆의 가장 긴 카드에 맞춰서 똑같이 쭈욱 늘어나게(stretch) 됩니다. 하지만 카드 '내부'의 콘텐츠는 일반적인 블록 레이아웃 방식을 따르기 때문에, 글의 양이 적은 카드의 경우 푸터(footer)가 카드 맨 아래에 붙지 않고 내용물 바로 밑으로 붕 뜨게 됩니다.

Two card components showing that the internals of the component do not stretch with the wrapper.

플렉스박스가 이 문제를 우아하게 해결해 줍니다! 카드를 플렉스 컨테이너로 만들고, 방향을 세로(flex-direction: column)로 줍니다. 그런 다음 카드 안의 메인 콘텐츠 영역에 flex: 1을 부여합니다. (이는 flex: 1 1 0의 단축형입니다.) 콘텐츠 영역은 스스로 쭉 늘어날 수 있는 유일한 요소이기 때문에, 카드 안에 남는 빈 공간을 모조리 차지하면서 자연스럽게 푸터(footer)를 카드 맨 밑바닥으로 확 밀어버립니다.

<div class="cards">
  <div class="card">
    <div class="content">
      <p>This card doesn't have much content.</p>
    </div>
    <footer>Card footer</footer>
  </div>
  <div class="card">
    <div class="content">
      <p>
        This card has a lot more content which means that it defines the height
        of the container the cards are in. I've laid the cards out using grid
        layout, so the cards themselves will stretch to the same height.
      </p>
    </div>
    <footer>Card footer</footer>
  </div>
</div>
body {
  font-family: sans-serif;
}
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-gap: 10px;
}

.card {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  display: flex; /* 카드 자체를 플렉스 컨테이너로 만듭니다 */
  flex-direction: column; /* 세로 방향으로 쌓이게 합니다 */
}

.card .content {
  padding: 10px;
  flex: 1 1 auto; /* 콘텐츠 영역이 남는 공간을 다 차지하며 쭉 늘어납니다! */
}

.card footer {
  background-color: rgb(96 139 168 / 0.2);
  padding: 10px;
}

미디어 객체 (Media objects)

이미지나 기타 미디어 요소 옆에 설명 텍스트가 나란히 붙어있는 '미디어 객체'는 웹 디자인의 매우 전형적인 패턴입니다. 이 미디어 객체는 이미지를 왼쪽에서 오른쪽으로, 오른쪽에서 왼쪽으로 자유롭게 뒤집을 수(flipped) 있어야 합니다.

우리는 플렉스박스를 사용하여, 미디어 객체 중 이미지가 들어있는 부분은 이미지 자체의 크기만큼만 자리를 차지하게 두고, 텍스트가 들어있는 콘텐츠 부분은 유연하게 늘어나서 나머지 공간을 모두 차지하도록 만들 수 있습니다.

아래 예제에서 .media 컨테이너는 align-items: flex-start로 정렬되어 있고, 텍스트가 있는 .content 부분은 flex: 1을 가져서 나머지 공간을 쭉 채우게 됩니다.

<div class="media">
  <div class="image">
    <img
      alt="A colorful balloon against a blue sky"
      src="[https://mdn.github.io/shared-assets/images/examples/balloon.jpg](https://mdn.github.io/shared-assets/images/examples/balloon.jpg)" />
  </div>
  <div class="content">
    This is the content of my media object. Items directly inside the flex
    container will be aligned to flex-start.
  </div>
</div>
img {
  max-width: 100%;
  display: block;
}

.media {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  align-items: flex-start;
}

.media .content {
  flex: 1; /* 텍스트 영역이 남은 공간을 모두 차지합니다. */
  padding: 10px;
}

미디어 객체 좌우 뒤집기 (Flipping the media object)

이미지를 오른쪽으로 보내고 텍스트를 왼쪽으로 오게 디스플레이를 뒤집고 싶다면, HTML 구조를 손댈 필요 없이 단순히 flex-direction 속성을 row-reverse로 설정하기만 하면 됩니다!

<div class="media flipped">
  <div class="image">
    <img
      alt="A colorful balloon against a blue sky"
      src="[https://mdn.github.io/shared-assets/images/examples/balloon.jpg](https://mdn.github.io/shared-assets/images/examples/balloon.jpg)" />
  </div>
  <div class="content">
    This is the content of my media object. Items directly inside the flex
    container will be aligned to flex-start.
  </div>
</div>
.media {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  align-items: flex-start;
}

.flipped {
  flex-direction: row-reverse; /* HTML 변경 없이 순서만 완벽하게 뒤집습니다! */
}

.media .content {
  flex: 1;
  padding: 10px;
}

폼 컨트롤 (Form controls)

플렉스박스는 특히 폼(form) 컨트롤을 스타일링할 때 유용합니다. 입력 폼에는 우리가 보통 가로로 일렬 정렬하고 싶어 하는 자잘한 요소들이 많죠. 검색 폼이나 이메일을 입력하는 뉴스레터 가입 폼처럼 <label>, <input>, 그리고 <button>이 하나로 결합된 패턴이 대표적입니다.

플렉스박스를 사용하면 단 몇 줄의 선언만으로 이런 레이아웃을 구현할 수 있습니다. 래퍼(wrapper)

display: flex를 주면 됩니다. 그리고 버튼과 라벨(label)은 늘어나지 않게 고정해 두고, <input> 필드(입력창)에만 flex 속성을 주어 사용 가능한 공간에 맞춰 유연하게 늘어났다 줄어들도록 만듭니다.

<form class="example">
  <div class="wrapper">
    <label for="text">Label</label>
    <input id="text" type="text" />
    <input type="submit" value="Send" />
  </div>
</form>
.wrapper {
  display: flex;
  border: 1px solid rgb(96 139 168);
}
.wrapper > * {
  padding: 10px;
  border: none;
  color: white;
}
.wrapper > input[type="text"] {
  background-color: rgb(96 139 168 / 0.5);
  flex: 1 1 auto; /* 텍스트 입력창만 부모 공간에 맞춰 쭉 늘어납니다! */
}
.wrapper input[type="submit"] {
  background-color: rgb(96 139 168);
}
.wrapper label {
  background-color: #666666;
}

이런 패턴은 나중에 폼 요소 라이브러리를 구축할 때 훨씬 쉽게 만들어줍니다. 요소가 늘어나도 전혀 깨지지 않거든요. 늘어나면 안 되는 요소들과 쫙 늘어나야 하는 요소들을 플렉스박스의 유연성(flexibility)에 맡겨 혼합 배치하는 아주 좋은 전략입니다.


결론 (Conclusion)

위의 패턴들을 탐구해 보면서, 여러분이 원하는 결과를 얻기 위해 플렉스박스를 어떤 방식으로 사용하는 것이 가장 좋을지 스스로 생각하는 법을 배우셨기를 바랍니다. 정답은 한 가지가 아닙니다. 늘어날 수 없는 아이템과 늘어나는 아이템을 혼합하거나, 콘텐츠를 기준으로 크기를 결정하게 하거나, 플렉스박스가 비율에 따라 공간을 나눠 갖게 할 수도 있습니다. 모든 것은 여러분의 선택에 달려있습니다!

여러분이 가진 콘텐츠를 가장 잘 표현할 방법이 무엇인지 고민해 보고, 플렉스박스(또는 Grid 등 다른 레이아웃 방식)가 어떻게 그 목표를 달성하게 도와줄 수 있는지 직접 시도해 보세요.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글