ToolPal
모니터에 CSS 코드가 표시된 코드 편집기

CSS 플렉스박스 생성기 가이드 — 시각적으로 레이아웃 만들기

📷 Sai Kiran Anagani / Pexels

CSS 플렉스박스 생성기 가이드 — 시각적으로 레이아웃 만들기

CSS Flexbox를 시각적으로 배우세요. flex-direction, justify-content, align-items 등 핵심 속성을 실시간 생성기와 예제로 이해합니다.

2026년 3월 30일9분 소요

CSS 레이아웃은 오랫동안 프론트엔드 개발자들의 골칫거리였다. floatclear를 조합하고, position: absolute로 강제로 위치를 잡고, 수직 가운데 정렬 하나 하려고 줄줄이 핵을 쓰던 시대가 있었다. Flexbox가 등장하기 전까지는.

지금은 Flexbox가 너무 보편화돼서 "이걸 어떻게 모를 수 있지?" 싶겠지만, 막상 속성이 많다 보니 처음 배울 때 헷갈리는 부분이 꽤 있다. 특히 justify-contentalign-items의 축 개념, flex-growflex-shrink의 동작 방식은 실제로 눈으로 보면서 익혀야 제대로 이해된다.

이 글에서는 Flexbox의 핵심 개념부터 실무에서 자주 쓰는 패턴까지 정리해본다.


Flexbox란 무엇인가

Flexbox는 Flexible Box Layout의 줄임말이다. 이름에서 알 수 있듯 컨테이너 안의 아이템들을 유연하게 배치하기 위한 CSS 레이아웃 모델이다.

핵심 개념은 두 가지다. 컨테이너아이템.

display: flex를 적용한 요소가 플렉스 컨테이너가 되고, 그 직계 자식 요소들이 플렉스 아이템이 된다. 컨테이너에는 배치 방식을 지정하는 속성들이 붙고, 아이템에는 개별 크기와 동작을 지정하는 속성들이 붙는다.

/* 이것만으로 div.container의 자식 요소들이 가로로 나란히 늘어선다 */
.container {
  display: flex;
}

Flexbox는 1차원 레이아웃이다. 행(row)이나 열(column) 방향 중 하나로 아이템을 배치한다. 2차원(행과 열 동시)이 필요하면 CSS Grid를 써야 한다.


축 개념 이해하기

Flexbox를 헷갈리게 만드는 주요 원인 중 하나가 축(axis) 개념이다.

Flexbox에는 두 개의 축이 있다.

  • 주 축(main axis): 아이템이 배치되는 방향. flex-direction으로 결정된다.
  • 교차 축(cross axis): 주 축과 수직인 방향.

flex-direction: row(기본값)이면 주 축은 수평(왼쪽→오른쪽), 교차 축은 수직(위→아래)이다. flex-direction: column이면 반대로 주 축이 수직, 교차 축이 수평이 된다.

이게 왜 중요하냐면, justify-content는 주 축 기준, align-items는 교차 축 기준으로 동작하기 때문이다. flex-direction이 바뀌면 이 둘의 동작 방향도 같이 바뀐다.


컨테이너 속성 총정리

flex-direction

아이템을 어느 방향으로 쌓을지 결정한다.

.container {
  display: flex;
  flex-direction: row;         /* 기본값: 가로 방향 */
  /* flex-direction: row-reverse; */   /* 가로 역방향 */
  /* flex-direction: column; */        /* 세로 방향 */
  /* flex-direction: column-reverse; */ /* 세로 역방향 */
}

justify-content

주 축 방향으로 아이템을 어떻게 정렬할지 결정한다. flex-direction: row라면 수평 정렬이다.

.container {
  display: flex;
  justify-content: flex-start;    /* 기본값: 시작점 정렬 */
  /* justify-content: flex-end;    끝점 정렬 */
  /* justify-content: center;      가운데 정렬 */
  /* justify-content: space-between; 양 끝에 붙이고 사이 균등 분배 */
  /* justify-content: space-around;  각 아이템 양옆에 균등한 여백 */
  /* justify-content: space-evenly;  모든 간격 동일 */
}

실무에서 가장 많이 쓰는 건 flex-start, center, space-between 세 가지다. 내비게이션에서 로고를 왼쪽에, 메뉴를 오른쪽에 붙이는 패턴에 space-between이 딱 맞는다.

align-items

교차 축 방향으로 아이템을 어떻게 정렬할지 결정한다. flex-direction: row라면 수직 정렬이다.

.container {
  display: flex;
  align-items: stretch;      /* 기본값: 컨테이너 높이만큼 늘리기 */
  /* align-items: flex-start;  교차 축 시작점 정렬 */
  /* align-items: flex-end;    교차 축 끝점 정렬 */
  /* align-items: center;      교차 축 가운데 정렬 */
  /* align-items: baseline;    텍스트 베이스라인 기준 정렬 */
}

flex-wrap

아이템이 컨테이너 너비를 초과할 때 어떻게 처리할지 결정한다.

.container {
  display: flex;
  flex-wrap: nowrap;   /* 기본값: 줄바꿈 없이 한 줄에 욱여넣기 */
  /* flex-wrap: wrap;     아이템이 넘치면 다음 줄로 내리기 */
  /* flex-wrap: wrap-reverse; 역방향으로 줄바꿈 */
}

반응형 카드 그리드를 만들 때 flex-wrap: wrapflex: 1 1 300px 조합이 자주 쓰인다. 화면 너비에 따라 자동으로 열 수가 조절된다.

gap

아이템 사이의 간격을 지정한다. 예전에는 margin으로 해결했는데, gap이 나오면서 훨씬 깔끔해졌다.

.container {
  display: flex;
  gap: 16px;            /* 행과 열 간격 동일 */
  /* gap: 16px 24px;   행 간격 16px, 열 간격 24px */
}

아이템 속성 총정리

flex-grow

컨테이너에 남은 공간이 있을 때 아이템이 얼마나 늘어날지 결정한다. 기본값은 0(늘어나지 않음).

.item {
  flex-grow: 0;  /* 기본값: 남은 공간 차지 안 함 */
}

.item-main {
  flex-grow: 1;  /* 남은 공간을 모두 차지 */
}

/* 여러 아이템이 있을 때는 비율로 나눔 */
.sidebar { flex-grow: 1; }
.content { flex-grow: 3; } /* 콘텐츠가 사이드바의 3배 너비 */

flex-shrink

컨테이너 공간이 부족할 때 아이템이 얼마나 줄어들지 결정한다. 기본값은 1(줄어들 수 있음).

.item {
  flex-shrink: 1;  /* 기본값: 공간 부족 시 줄어듦 */
}

.item-fixed {
  flex-shrink: 0;  /* 절대 줄어들지 않음 */
}

사이드바처럼 고정 너비를 유지해야 하는 요소에 flex-shrink: 0을 쓰면 좋다.

flex-basis

아이템의 기본 크기를 지정한다. width와 비슷하지만 flex-direction에 따라 너비나 높이가 된다.

.item {
  flex-basis: auto;   /* 기본값: 콘텐츠 크기 기준 */
  /* flex-basis: 200px; */
  /* flex-basis: 30%; */
  /* flex-basis: 0;      flex-grow로만 크기 결정 */
}

flex 단축 속성

flex-grow, flex-shrink, flex-basis를 한 번에 지정한다. 이 방식을 쓰는 게 더 간결하다.

.item {
  flex: 0 1 auto;   /* 기본값: grow 0, shrink 1, basis auto */
}

.item-flexible {
  flex: 1;          /* flex: 1 1 0과 동일 — 공간을 균등하게 나눔 */
}

.item-fixed {
  flex: 0 0 200px;  /* 200px 고정 너비 */
}

align-self

특정 아이템만 교차 축 정렬을 다르게 하고 싶을 때 쓴다. 컨테이너의 align-items를 개별 아이템 레벨에서 오버라이드한다.

.container {
  display: flex;
  align-items: center;  /* 기본적으로 모두 가운데 정렬 */
}

.item-special {
  align-self: flex-end;  /* 이 아이템만 아래쪽 정렬 */
}

실무에서 자주 쓰는 패턴

완전한 가운데 정렬

예전에는 수직 가운데 정렬이 악명 높았는데, Flexbox로는 두 줄이면 된다.

.container {
  display: flex;
  justify-content: center;  /* 수평 가운데 */
  align-items: center;      /* 수직 가운데 */
  min-height: 100vh;        /* 뷰포트 전체 높이 */
}

로딩 스피너, 모달, 히어로 섹션 등에서 항상 쓰는 패턴이다.

내비게이션 바

로고는 왼쪽, 메뉴는 오른쪽, 수직으로는 가운데 정렬.

.navbar {
  display: flex;
  justify-content: space-between;  /* 로고와 메뉴 양 끝 배치 */
  align-items: center;             /* 수직 가운데 정렬 */
  padding: 0 24px;
  height: 60px;
}

.nav-menu {
  display: flex;       /* 메뉴 아이템도 flex로 */
  gap: 24px;
  list-style: none;
  margin: 0;
  padding: 0;
}

반응형 카드 그리드

flex-wrapflex 단축 속성을 조합하면 미디어 쿼리 없이도 기본적인 반응형 그리드를 만들 수 있다.

.card-grid {
  display: flex;
  flex-wrap: wrap;    /* 넘치면 줄바꿈 */
  gap: 16px;
}

.card {
  flex: 1 1 280px;    /* 최소 280px, 남은 공간 균등 분배 */
  /* 화면이 좁아지면 자동으로 한 열로 바뀜 */
}

사이드바 + 메인 콘텐츠 레이아웃

.layout {
  display: flex;
  gap: 24px;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 260px;     /* 고정 너비 260px, 줄어들지 않음 */
}

.main-content {
  flex: 1;             /* 나머지 공간 모두 차지 */
  min-width: 0;        /* 오버플로우 방지용 */
}

여기서 .main-contentmin-width: 0을 추가하는 이유가 있다. 플렉스 아이템의 기본 min-widthauto인데, 이러면 콘텐츠가 넘쳐도 아이템이 줄어들지 않는 버그가 생긴다. min-width: 0으로 명시적으로 줄어들 수 있게 해줘야 한다.

버튼 그룹

.button-group {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* 특정 버튼을 오른쪽 끝으로 밀기 */
.button-right {
  margin-left: auto;   /* 남은 공간을 왼쪽 마진으로 모두 소비 */
}

margin-left: auto는 Flexbox에서 특정 아이템을 반대편 끝으로 밀어내는 트릭이다. justify-content로 전체 배치를 바꾸지 않고도 특정 아이템만 분리할 수 있어서 유용하다.


Flexbox 생성기로 시각적으로 익히기

Flexbox를 글로만 읽으면 한계가 있다. 실제로 속성 값을 바꿔가면서 레이아웃이 어떻게 변하는지 눈으로 확인하는 게 훨씬 빠르다.

toolboxhubs.com/ko/tools/css-flexbox-generator에서 플렉스 컨테이너와 아이템 속성을 실시간으로 조작하고 결과를 바로 확인할 수 있다. 원하는 레이아웃을 만들면 CSS 코드도 자동으로 생성되니, 그대로 프로젝트에 붙여넣기만 하면 된다.

justify-contentalign-items의 조합이 헷갈릴 때 직접 값을 바꿔가며 확인하면 금방 감이 온다.


Flexbox vs CSS Grid

두 가지를 언제 써야 하는지 기준이 명확하지 않아 헷갈리는 경우가 많다.

상황추천
내비게이션 바, 버튼 그룹처럼 단순히 가로로 나열Flexbox
카드 목록, 태그 목록처럼 줄바꿈이 자연스럽게 이뤄져야 하는 경우Flexbox
복잡한 페이지 레이아웃 (헤더, 사이드바, 메인, 푸터)Grid
행과 열 위치를 동시에 명시적으로 제어해야 할 때Grid
아이템 수가 동적으로 변하는 자동 배치Grid

사실 현대 프론트엔드에서는 둘 중 하나만 쓰는 게 아니라 같이 쓰는 경우가 훨씬 많다. 전체 페이지 구조는 Grid로 잡고, 각 섹션 내부 컴포넌트는 Flexbox로 배치하는 식이다.


흔한 실수 모음

1. flex-direction을 바꿨는데 justify-content가 예상대로 안 된다

flex-direction: column으로 바꾸면 주 축이 수직 방향이 된다. 이때 justify-content는 수직 정렬, align-items는 수평 정렬을 담당한다. row 기준으로 외운 것과 반대가 되니까 헷갈리기 쉽다.

2. 아이템이 컨테이너를 뚫고 나온다

flex-wrap: nowrap(기본값) 상태에서 아이템이 너무 많으면 컨테이너를 초과한다. flex-wrap: wrap으로 바꾸거나, overflow: hidden을 추가하거나, 아이템에 min-width: 0을 설정해보자.

3. flex: 1이 예상대로 작동하지 않는다

flex: 1flex: 1 1 0으로 해석된다. flex-basis가 0이 되기 때문에 콘텐츠 크기를 무시하고 남은 공간을 균등하게 나눈다. 콘텐츠 크기를 고려한 균등 분배를 원한다면 flex: 1 1 auto나 그냥 flex-grow: 1을 써야 한다.

4. align-content vs align-items 혼동

align-items는 단일 행에서 아이템의 교차 축 정렬이고, align-contentflex-wrap으로 여러 줄이 생겼을 때 줄들 사이의 간격과 정렬을 결정한다. 한 줄짜리 컨테이너에서 align-content는 효과가 없다.

5. 이미지를 플렉스 아이템으로 쓸 때 비율이 깨진다

이미지는 기본적으로 align-items: stretch의 영향을 받아 세로로 늘어날 수 있다. 이미지나 이미지를 감싼 컨테이너에 align-self: flex-start 또는 align-items: flex-start를 추가해주면 해결된다.


order 속성으로 시각적 순서 바꾸기

HTML 마크업 순서를 바꾸지 않고 시각적 순서만 변경할 때 order 속성을 쓴다. 기본값은 0이고, 숫자가 작을수록 앞에 배치된다.

/* 모바일에서 이미지를 텍스트 위에 보이게 하기 */
@media (max-width: 768px) {
  .content-text  { order: 2; }
  .content-image { order: 1; }
}

접근성 측면에서는 주의가 필요하다. 스크린 리더는 시각적 순서가 아니라 DOM 순서를 따른다. order로 시각 순서를 바꾸면 시각 사용자와 스크린 리더 사용자가 다른 순서로 콘텐츠를 경험하게 된다.


실전 예제: 댓글 컴포넌트

실제로 자주 마주치는 UI 패턴 하나를 Flexbox로 만들어보자.

/* 아바타 + 내용이 가로로, 내용 안에서 이름과 텍스트가 세로로 쌓이는 댓글 구조 */
.comment {
  display: flex;
  gap: 12px;
  padding: 16px;
}

.comment-avatar {
  flex: 0 0 40px;   /* 40px 고정, 줄어들지 않음 */
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
}

.comment-body {
  flex: 1;          /* 남은 공간 모두 차지 */
  min-width: 0;     /* 긴 텍스트 오버플로우 방지 */
}

.comment-header {
  display: flex;
  justify-content: space-between;  /* 이름 왼쪽, 날짜 오른쪽 */
  align-items: baseline;           /* 베이스라인 기준 정렬 */
  margin-bottom: 4px;
}

.comment-name {
  font-weight: 600;
}

.comment-date {
  font-size: 0.75rem;
  color: #888;
}

이 구조에서 min-width: 0이 없으면 긴 단어나 URL이 컨테이너를 뚫고 나오는 버그가 생긴다. 실무에서 꽤 자주 만나는 문제다.


정리

Flexbox는 CSS 레이아웃의 판도를 바꾼 기술이다. floatclear로 고통받던 시대를 끝내고, 수직 가운데 정렬을 두 줄로 해결할 수 있게 해줬다.

핵심을 정리하면 이렇다.

  • 주 축과 교차 축 개념을 이해하면 나머지는 자연스럽게 따라온다
  • justify-content는 주 축, align-items는 교차 축
  • flex-direction이 바뀌면 두 속성의 담당 방향도 바뀐다
  • flex: 1로 남은 공간을 균등하게 나눌 수 있다
  • flex-shrink: 0으로 고정 크기를 유지할 수 있다
  • margin: auto는 플렉스 아이템을 반대편으로 밀어내는 트릭이다
  • min-width: 0은 오버플로우 버그의 자주 쓰이는 해결책이다

Flexbox와 Grid는 서로 경쟁 관계가 아니다. 두 가지를 함께 쓰는 게 현대 CSS 레이아웃의 표준 방식이다. 1차원 배치는 Flexbox, 2차원 레이아웃은 Grid라고 기억해두면 선택에서 헷갈리지 않을 것이다.

자주 묻는 질문

이 글 공유하기

XLinkedIn

관련 글