Tailwind CSS flex 레이아웃 깨질 때 확인할 것

2026.05.15·수정 2026.07.19·약 12분

Tailwind CSS flex 레이아웃이 깨질 때 먼저 확인할 것

Tailwind CSS에서 flex 레이아웃이 예상과 다르게 깨질 때는 클래스를 계속 덧붙이기보다 부모의 방향, 주축과 교차축, 자식 요소의 최소 너비, grow/shrink 동작, 줄바꿈 여부를 나눠서 확인해야 합니다. 특히 카드형 UI, 상품 리스트, 관리자 목록처럼 요소가 반복되는 화면에서는 flex-1, min-w-0, shrink-0, flex-wrap, basis-*의 역할을 구분하는 것이 먼저입니다.

깨진 모양을 먼저 분류하기

Tailwind flex 레이아웃에서 부모 방향과 주축 교차축을 구분하는 구조 설명

Tailwind CSS로 카드, 버튼 그룹, 상품 리스트를 만들다 보면 flex를 넣었는데도 요소가 한쪽으로 밀리거나, 텍스트가 영역 밖으로 튀어나가거나, 모바일에서 가로 스크롤이 생기는 경우가 있습니다. 이때 w-full, overflow-hidden, justify-between을 바로 붙이면 겉모양은 잠깐 맞을 수 있지만 원인이 남습니다.

먼저 깨진 모양을 분류해야 합니다. 요소가 옆으로 넘치는 문제인지, 세로 정렬이 맞지 않는 문제인지, 카드 너비가 제각각인 문제인지에 따라 확인할 클래스가 달라집니다. flex 문제는 대부분 부모의 배치 방향, 주축 기준의 정렬, 자식 요소의 최소 너비와 기본 크기 계산이 같이 어긋나면서 생깁니다.

예를 들어 상품 카드 안에서 썸네일은 왼쪽에 고정하고, 오른쪽에는 상품명과 가격을 넣는 구조를 생각할 수 있습니다. 상품명이 길어지는 순간 오른쪽 영역이 줄어들지 못하면 카드 전체가 밀립니다. 이 문제는 텍스트가 길어서 생긴 것처럼 보이지만, 실제로는 flex item의 최소 너비가 자동으로 잡혀 있는 문제일 수 있습니다.

주축과 교차축 다시 확인하기

flex 레이아웃을 볼 때 첫 번째 기준은 flex-row인지 flex-col인지입니다. Tailwind 공식 문서 기준으로 justify-*는 컨테이너의 main axis, 즉 주축을 따라 항목을 배치합니다. items-*는 교차축 정렬을 맡기 때문에, 화면을 보면서 “가운데 정렬이 안 된다”라고만 판단하면 어느 축에서 어긋났는지 놓치기 쉽습니다.

flex-row에서는 왼쪽에서 오른쪽으로 흐르는 방향이 주축입니다. 그래서 justify-between은 가로 방향의 남는 공간을 요소 사이로 보냅니다. 반대로 flex-col에서는 위에서 아래로 흐르는 방향이 주축이므로 같은 justify-between이라도 세로 방향의 남는 공간을 벌립니다.

카드 하단 버튼을 아래에 붙이고 싶은데 justify-between을 넣어도 변화가 없다면, 부모가 실제로 세로 방향 flex인지 확인해야 합니다. 부모에 flex flex-col이 없거나 카드 자체의 높이가 확보되어 있지 않으면 벌어질 공간이 없습니다.

<article class="flex min-h-[220px] flex-col rounded-xl border p-4">
 <div>
  <h3 class="text-base font-semibold">상품명</h3>
  <p class="mt-2 text-sm text-gray-600">상품 설명이 들어가는 영역</p>
 </div>

 <button class="mt-auto w-full rounded-lg border px-4 py-2">자세히 보기</button>
</article>

이 구조에서는 버튼에 mt-auto를 둬서 남는 세로 공간을 버튼 위쪽으로 보냅니다. 카드 높이가 일정하지 않은 상태에서 무작정 justify-between을 넣는 것보다, 어떤 요소를 아래로 밀 것인지가 더 분명하게 드러납니다.

텍스트와 버튼이 밀리는 이유

모바일에서 flex 레이아웃이 깨질 때 자주 놓치는 부분이 min-w-0입니다. Tailwind의 min-w-0은 해당 요소의 최소 너비를 0으로 낮추는 유틸리티입니다. flex item이 내부 콘텐츠의 최소 너비를 기준으로 줄어들지 못하면 긴 상품명, 긴 URL, 긴 버튼 문구가 부모 영역을 넘어갈 수 있습니다.

truncate만 넣으면 해결될 것처럼 보이지만, 텍스트를 감싼 영역이 줄어들 수 없는 상태라면 말줄임도 기대한 대로 작동하지 않습니다. Tailwind의 truncate는 overflow hidden, text-overflow ellipsis, nowrap 조합이므로, 줄어들어야 하는 오른쪽 영역에는 min-w-0을 넣고 남는 공간을 가져가야 하는 영역에는 flex-1을 함께 확인해야 합니다.

<div class="flex items-center gap-3 rounded-xl border p-4">
 <img class="h-16 w-16 shrink-0 rounded-lg object-cover" src="" alt="상품 썸네일">

 <div class="min-w-0 flex-1">
  <p class="truncate text-sm font-semibold">모바일 화면에서 길어질 수 있는 상품명 또는 게시글 제목</p>
  <p class="mt-1 text-sm text-gray-500">24,000원</p>
 </div>

 <button class="shrink-0 rounded-lg border px-3 py-2 text-sm">선택</button>
</div>

썸네일과 버튼은 크기가 유지되어야 하므로 shrink-0을 둡니다. 가운데 텍스트 영역은 남는 공간을 가져가되 필요하면 줄어들어야 하므로 flex-1 min-w-0이 맞습니다. Tailwind의 flex-1은 flex item이 grow와 shrink에 참여하도록 만드는 축약 유틸리티이므로, 고정 요소와 유동 요소의 역할을 분리해서 써야 합니다.

증상 먼저 확인할 클래스 확인 기준
텍스트가 카드 밖으로 나감 min-w-0, truncate 줄어들어야 할 자식 영역이 실제로 줄어들 수 있는지 확인
아이콘이나 썸네일 크기가 찌그러짐 shrink-0 고정 크기를 유지해야 하는 요소인지 확인
카드가 한 줄에 억지로 붙음 flex-wrap, basis-* 줄바꿈이 필요한 구조인지 확인
정렬 방향이 예상과 다름 flex-row, flex-col 주축이 가로인지 세로인지 먼저 확인

줄바꿈과 줄어듦을 분리해서 보기

여러 개의 카드를 가로로 배치할 때는 flex-wrapbasis-*를 함께 봐야 합니다. Tailwind의 flex-wrap은 flex item이 다음 줄로 내려갈 수 있게 하고, basis-*는 flex item의 주축 기본 크기를 정합니다. 화면이 좁아졌을 때 카드가 더 작아져야 하는지, 다음 줄로 내려가야 하는지 기준이 없으면 레이아웃이 불안정해집니다.

쇼핑몰 카테고리 카드처럼 항목 수가 늘어나는 UI에서는 카드가 계속 줄어드는 것보다 일정 너비 이하에서 다음 줄로 내려가는 구성이 자연스럽습니다. 부모에는 flex flex-wrap gap-4를 두고, 자식에는 basis-*나 반응형 너비를 지정해 카드의 기본 크기를 잡습니다.

<ul class="flex flex-wrap gap-4">
 <li class="basis-full rounded-xl border p-4 sm:basis-[calc(50%_-_8px)] lg:basis-[calc(25%_-_12px)]">
  카테고리 카드
 </li>
 <li class="basis-full rounded-xl border p-4 sm:basis-[calc(50%_-_8px)] lg:basis-[calc(25%_-_12px)]">
  카테고리 카드
 </li>
</ul>

basis는 flex item이 주축에서 차지하려는 기본 크기입니다. Tailwind의 basis-* 유틸리티는 이 초기 크기를 지정하고, 실제 배치에서는 grow, shrink, 남는 공간, 줄바꿈 여부가 함께 계산됩니다. 그래서 단순히 너비만 맞추는 문제가 아니라, 부모 안에서 남는 공간을 어떻게 나눌지까지 같이 봐야 합니다.

수정 후 다시 볼 체크리스트

Tailwind flex 레이아웃 문제 해결을 위한 모바일 반응형 체크리스트

flex 레이아웃을 고칠 때는 눈에 보이는 깨짐을 바로 덮기보다 확인 순서를 고정해두는 편이 낫습니다. 첫 번째는 부모가 실제로 flex인지 확인하는 것입니다. 그 다음 flex-rowflex-col 중 어떤 방향인지 보고, justify-*items-*가 어느 축에 적용되는지 다시 확인합니다.

두 번째는 자식 요소의 크기입니다. 고정되어야 하는 요소에는 shrink-0, 남는 공간을 써야 하는 요소에는 flex-1, 줄어들며 말줄임되어야 하는 영역에는 min-w-0truncate가 필요한지 봅니다. 각 클래스는 최소 너비, grow/shrink, 텍스트 overflow를 다르게 다루므로 하나로 대신하기 어렵습니다.

세 번째는 반응형 기준입니다. 데스크톱에서는 문제가 없어도 모바일에서만 깨진다면 sm:, md:, lg: 기준으로 방향이나 너비가 바뀌는지 확인해야 합니다. 특히 md:flex-row를 넣고 기본값을 지정하지 않으면 모바일에서 의도와 다른 방향으로 쌓일 수 있습니다.

<section class="flex flex-col gap-4 md:flex-row">
 <aside class="w-full shrink-0 rounded-xl border p-4 md:w-64">
  필터 영역
 </aside>

 <div class="min-w-0 flex-1 rounded-xl border p-4">
  목록 영역
 </div>
</section>

이 구조에서는 모바일에서 필터와 목록이 세로로 쌓이고, md 이상에서는 가로로 배치됩니다. 목록 영역에는 min-w-0 flex-1을 넣어 긴 제목이나 테이블성 콘텐츠가 들어와도 부모 너비 안에서 계산되도록 합니다. 사이드 영역은 너비를 유지해야 하므로 shrink-0을 둡니다.

마무리 점검

Tailwind CSS flex 레이아웃이 깨질 때는 클래스를 많이 아는 것보다 확인 순서가 더 중요합니다. 부모의 flex 방향을 보고, 주축과 교차축을 구분한 뒤, 자식 요소가 줄어들어야 하는지 유지되어야 하는지 판단해야 합니다.

모바일 화면에서 가로 스크롤이 생기거나 텍스트가 버튼을 밀어내는 문제는 min-w-0, flex-1, shrink-0 조합을 먼저 의심할 수 있습니다. 카드나 리스트가 여러 줄로 내려가야 하는 구조라면 flex-wrapbasis-*도 같이 확인해야 합니다.

다음에 비슷한 문제가 생기면 “정렬이 안 된다”에서 멈추지 말고 축, 크기, 줄바꿈, 반응형 기준으로 나눠서 보면 됩니다. 이렇게 원인을 분리해두면 임시로 덮는 코드가 줄고, 다른 화면으로 확장할 때도 같은 기준을 다시 사용할 수 있습니다.

공식 기준은 Tailwind flex-direction, Tailwind justify-content, Tailwind flex, Tailwind flex-shrink, Tailwind min-width, Tailwind flex-wrap, Tailwind flex-basis, Tailwind text-overflow 문서에서 다시 확인할 수 있습니다.

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

댓글 남기기