Skip to main content
Summary

Flexbox는 정렬을 맡기는 방법이다

이전 장에서는 block, inline, inline-block으로 요소가 한 줄을 차지하는지, 옆으로 붙는지 살펴보았다. 이번 장에서는 한 걸음 더 나아가 여러 요소를 보기 좋게 정렬하는 방법을 배운다.

Flexbox는 CSS에서 요소들을 한 방향으로 정렬하기 위한 배치 방식이다. 식탁 위에 컵 여러 개를 올려놓고 "가운데로 모아 줘", "간격을 똑같이 벌려 줘", "왼쪽과 오른쪽 끝으로 나눠 줘"라고 말하는 것과 비슷하다.

Flexbox를 쓰면 이런 문제를 훨씬 단순하게 해결할 수 있다.

  • 메뉴 항목을 가로로 나란히 놓기

  • 버튼 두 개를 일정한 간격으로 배치하기

  • 카드 목록 사이의 간격을 맞추기

  • 배너 안에서 문구는 왼쪽, 버튼은 오른쪽에 놓기

  • 로고와 메뉴가 있는 상단 헤더 정리하기

핵심은 하나다. 정렬하고 싶은 요소들의 부모에게 display: flex;를 준다.

Flexbox로 가로 정렬과 가운데 정렬 끝내기AI 생성 이미지

부모에게 display: flex를 준다

Flexbox에서 가장 먼저 기억할 말은 부모에게 적용한다는 것이다.

예를 들어 메뉴 항목 세 개가 있다고 해 보자.

<nav class="menu">
  <a href="#">소개</a>
  <a href="#">서비스</a>
  <a href="#">문의</a>
</nav>

여기서 실제로 나란히 놓고 싶은 것은 a 태그들이다. 하지만 CSS는 각각의 a가 아니라, 그들을 감싸고 있는 부모인 .menu에 준다.

.menu {
  display: flex;
}

이 한 줄을 넣으면 .menu 안의 자식 요소인 링크들이 기본적으로 가로 방향으로 나란히 배치된다.

.menu {
  display: flex;
  gap: 24px;
}

여기에 gap을 추가하면 메뉴 사이 간격이 일정해진다. gap은 요소와 요소 사이에 끼워 넣는 일정한 간격이다. 예전에는 각 메뉴에 margin-right를 따로 주는 일이 많았지만, Flexbox에서는 부모에게 gap을 주는 방식이 더 깔끔하다.

정리하면 이렇다.

.menu {
  display: flex; /* 자식들을 한 줄 흐름으로 배치 */
  gap: 24px;     /* 자식들 사이 간격 */
}

가로 정렬은 justify-content로 조절한다

justify-content는 Flexbox 안에서 자식 요소들을 가로 방향으로 어떻게 배치할지 정하는 속성이다. 긴 선반 위에 물건들을 왼쪽에 둘지, 가운데에 모을지, 양쪽 끝으로 벌릴지 정한다고 생각하면 된다.

대표 값만 먼저 익히면 충분하다.

.menu {
  display: flex;
  justify-content: center;
}

이렇게 하면 메뉴들이 가운데로 모인다.

자주 쓰는 값은 다음과 같다.

  • flex-start: 왼쪽부터 배치

  • center: 가운데 배치

  • flex-end: 오른쪽으로 배치

  • space-between: 첫 요소는 왼쪽 끝, 마지막 요소는 오른쪽 끝에 두고 사이를 벌림

상단 헤더에서 로고는 왼쪽, 메뉴는 오른쪽에 놓고 싶을 때 space-between이 특히 자주 쓰인다.

.header {
  display: flex;
  justify-content: space-between;
}

이 코드는 "헤더 안의 요소들을 양쪽 끝으로 나누어 배치해 줘"라는 뜻이다.

세로 가운데 정렬은 align-items로 맞춘다

가로 정렬을 justify-content로 다뤘다면, 세로 정렬은 align-items로 다룬다.

align-items는 Flexbox 안에서 자식 요소들의 높낮이를 맞추는 속성이다. 서로 키가 다른 물건들을 한 줄에 세워 놓고 위쪽에 맞출지, 가운데 높이에 맞출지 정하는 것과 비슷하다.

버튼과 문구가 있는 배너를 예로 보자.

<div class="event-banner">
  <p>여름 할인 이벤트가 진행 중입니다.</p>
  <a href="#">자세히 보기</a>
</div>

완성 결과는 이렇다. 문구는 왼쪽에, 버튼은 오른쪽에 있고, 둘은 세로 가운데에 가지런히 놓인다.

.event-banner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  background-color: #eff6ff;
  border-radius: 12px;
}

여기서 각 줄의 역할은 분명하다.

display: flex;

자식 요소인 문구와 버튼을 한 줄 흐름으로 바꾼다.

justify-content: space-between;

문구와 버튼을 양쪽 끝으로 벌린다.

align-items: center;

문구와 버튼의 세로 위치를 가운데로 맞춘다.

Flexbox에서 가운데 정렬을 만들 때 가장 많이 쓰는 조합은 다음이다.

.box {
  display: flex;
  justify-content: center;
  align-items: center;
}

이 코드는 자식 요소를 가로 가운데, 세로 가운데에 놓는다. 팝업 안의 버튼, 카드 안의 아이콘, 빈 상태 안내 문구를 가운데 놓을 때 자주 사용한다.

gap으로 간격을 일정하게 만든다

화면이 어수선해 보이는 이유 중 하나는 간격이 제각각이기 때문이다. 어떤 메뉴는 너무 붙어 있고, 어떤 버튼은 멀리 떨어져 있으면 화면의 질서가 약해진다.

Flexbox에서는 gap으로 이 문제를 쉽게 줄일 수 있다.

<div class="button-group">
  <button>취소</button>
  <button>저장</button>
</div>
.button-group {
  display: flex;
  gap: 12px;
}

이렇게 하면 두 버튼 사이가 항상 12px만큼 떨어진다.

카드 목록에도 같은 생각을 적용할 수 있다.

.card-list {
  display: flex;
  gap: 20px;
}

단, 카드가 많아 화면을 넘어갈 수 있다면 flex-wrap을 함께 쓸 수 있다. flex-wrap은 공간이 부족할 때 다음 줄로 내려가게 하는 속성이다.

.card-list {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

지금은 flex-wrap을 깊게 외울 필요는 없다. "카드가 한 줄에 다 안 들어가면 다음 줄로 내려가게 할 수 있다" 정도로 이해하면 충분하다.

flex-direction으로 방향을 바꾼다

Flexbox는 기본적으로 자식 요소들을 가로로 배치한다. 이 기본 방향은 flex-direction: row;이다.

.menu {
  display: flex;
  flex-direction: row;
}

row는 행, 즉 가로줄이라는 뜻이다. 기본값이라 보통은 생략한다.

반대로 세로로 쌓고 싶을 때는 column을 쓴다.

.menu {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

이렇게 하면 메뉴 항목이 위에서 아래로 쌓인다.

이 사고방식은 반응형 화면을 만들 때 중요하다. PC에서는 가로로 넓게 펼치고, 모바일에서는 세로로 쌓는다.

예를 들어 카드 목록을 PC에서는 가로로 보여 주고, 작은 화면에서는 세로로 보여 주고 싶다면 다음처럼 생각할 수 있다.

.card-list {
  display: flex;
  gap: 20px;
}

@media (max-width: 600px) {
  .card-list {
    flex-direction: column;
  }
}

@media는 조건을 붙이는 CSS 문장이다. 위 코드는 "화면 너비가 600px 이하일 때는 카드 목록을 세로 방향으로 바꿔 줘"라는 뜻이다. 반응형 CSS는 뒤에서 더 자세히 다루므로, 지금은 방향을 바꾸는 감각만 잡으면 된다.

실습: 로고와 메뉴가 있는 상단 헤더 만들기

이번에는 실제 웹사이트에서 자주 보는 상단 헤더를 정리해 보자.

완성 결과는 다음과 같다.

  • 로고는 왼쪽에 있다.

  • 메뉴는 오른쪽에 가로로 놓인다.

  • 로고와 메뉴는 세로 가운데가 맞는다.

  • 메뉴 사이 간격은 일정하다.

HTML은 다음과 같다.

<header class="site-header">
  <div class="logo">Fresh Market</div>

  <nav class="site-menu">
    <a href="#">상품</a>
    <a href="#">이벤트</a>
    <a href="#">고객센터</a>
  </nav>
</header>

먼저 헤더 전체를 Flexbox로 만든다.

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 24px;
  border-bottom: 1px solid #e5e7eb;
}

display: flex;는 로고와 메뉴를 한 줄에 놓는다. justify-content: space-between;은 로고와 메뉴를 양쪽 끝으로 보낸다. align-items: center;는 로고와 메뉴의 세로 위치를 가운데로 맞춘다.

다음으로 메뉴 자체도 Flexbox로 만든다.

.site-menu {
  display: flex;
  gap: 20px;
}

여기서 중요한 점이 있다. .site-header도 Flexbox이고, .site-menu도 Flexbox이다.

  • .site-header는 로고와 메뉴 묶음의 배치를 담당한다.

  • .site-menu는 메뉴 안의 링크들을 배치한다.

부모가 달라지면 Flexbox가 정리하는 대상도 달라진다. 이 감각이 생기면 복잡한 화면도 작은 묶음으로 나누어 볼 수 있다.

마지막으로 링크의 기본 밑줄과 색을 정리한다.

.site-menu a {
  color: #374151;
  text-decoration: none;
  font-size: 15px;
}

.logo {
  font-weight: 700;
  color: #111827;
}

이제 헤더는 훨씬 안정적으로 보인다.

모바일에서는 세로로 바꿔 보기

화면이 좁아지면 로고와 메뉴가 한 줄에 모두 들어가기 어려울 수 있다. 이때는 헤더를 세로로 쌓고 가운데 정렬할 수 있다.

@media (max-width: 600px) {
  .site-header {
    flex-direction: column;
    gap: 14px;
  }
}

이 코드는 작은 화면에서 .site-header 안의 로고와 메뉴를 위아래로 쌓는다. gap: 14px;는 로고와 메뉴 사이의 간격을 만든다.

필요하다면 메뉴도 세로로 바꿀 수 있다.

@media (max-width: 600px) {
  .site-menu {
    flex-direction: column;
    align-items: center;
    gap: 10px;
  }
}

PC와 모바일을 완전히 따로 만든다고 생각하지 않아도 된다. 기본 모양을 먼저 만들고, 좁은 화면에서 방향만 바꾼다고 생각하면 훨씬 쉽다.

자주 헷갈리는 지점 체크리스트

Flexbox가 적용되지 않을 때는 다음을 확인해 보자.

  • display: flex;를 자식이 아니라 부모에게 주었는가?

  • 정렬하고 싶은 요소들이 같은 부모 안에 들어 있는가?

  • 가로 정렬 문제인데 align-items만 바꾸고 있지는 않은가?

  • 세로 가운데 정렬 문제인데 justify-content만 바꾸고 있지는 않은가?

  • 요소 사이 간격을 각 요소의 margin으로 제각각 주고 있지는 않은가?

  • 모바일에서 가로 배치가 답답하면 flex-direction: column;을 고려했는가?

처음에는 justify-content와 align-items가 자주 헷갈린다. 이때는 이렇게 기억하면 좋다.

  • justify-content: 주된 방향으로 정렬한다. 기본 Flexbox에서는 보통 가로 정렬이다.

  • align-items: 그 반대 방향으로 맞춘다. 기본 Flexbox에서는 보통 세로 정렬이다.

다만 flex-direction: column;으로 방향을 바꾸면 두 속성이 다루는 방향도 함께 달라진다. 처음에는 기본값인 가로 배치에서 충분히 연습한 뒤, 세로 배치를 다루면 이해하기 쉽다.

작은 실습: 흩어진 링크를 메뉴처럼 정리하기

수정 전에는 링크들이 줄줄이 붙어 있거나 간격이 일정하지 않다.

<div class="footer-links">
  <a href="#">회사 소개</a>
  <a href="#">이용약관</a>
  <a href="#">개인정보처리방침</a>
</div>

수정 전 CSS가 다음과 같다고 해 보자.

.footer-links a {
  margin-right: 8px;
}

마지막 링크 뒤에도 불필요한 여백이 생기고, 간격 관리가 링크마다 흩어진다.

수정 후에는 부모에게 Flexbox를 적용한다.

.footer-links {
  display: flex;
  justify-content: center;
  gap: 16px;
}

.footer-links a {
  color: #4b5563;
  text-decoration: none;
}

수정 전후를 비교하면 차이가 분명하다.

구분수정 전수정 후
배치 기준각 링크에 여백을 따로 줌부모가 링크들을 정렬함
간격마지막 요소 처리에 신경 써야 함gap으로 일정하게 관리함
가운데 정렬별도 조정이 필요함justify-content: center로 해결함
유지보수링크가 늘면 손볼 곳이 많음링크가 늘어도 구조가 단순함

Flexbox의 핵심은 복잡한 계산이 아니다. 정렬하고 싶은 요소들을 하나의 묶음으로 보고, 그 부모에게 "가로로 놓아 줘", "가운데 맞춰 줘", "사이를 일정하게 벌려 줘"라고 말하는 것이다. 이 감각만 익혀도 메뉴, 버튼 묶음, 카드 목록, 상단 헤더를 훨씬 안정적으로 다룰 수 있다.

책 목록

비개발자를 위한 CSS 입문: 눈으로 이해하고 바로 고치는 쉬운 스타일링

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기