Flex 레이아웃에서 텍스트 말줄임이 안 될 때 - min-width의 비밀

이런 경험 있으시죠?

.description {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

분명 말줄임 처리를 위한 CSS 3종 세트를 다 적었는데, 텍스트가 부모 영역을 뚫고 나가는 현상. 저도 매번 겪었고, 매번 “왜 안 되지?”라고 당황했습니다.

특히 Flex 레이아웃을 사용할 때 이런 일이 자주 일어나는데요, 오늘은 그 원인과 해결 방법을 정리해봅니다.

실제 사례: 카테고리 페이지의 설명 텍스트

제가 최근 겪었던 실제 사례입니다. 카테고리 페이지에서 글 설명이 한 줄 말줄임 처리가 안 되는 문제였어요.

HTML 구조

<ul class="category-posts-list">
  <li class="category-post-item">
    <a href="/post" class="category-post-link">
      <div class="category-post-main">
        <h4 class="category-post-title">글 제목</h4>
        <p class="category-post-description">
          아주 긴 설명 텍스트가 여기 들어가는데 이게 한 줄로 잘리지 않고 계속 이어집니다...
        </p>
      </div>
      <div class="category-post-meta">
        <time>2025.10.17</time>
      </div>
    </a>
  </li>
</ul>

처음 시도한 CSS (실패)

.category-post-description {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

결과: 여전히 텍스트가 영역을 벗어남 😰

왜 안 될까? Flex의 min-width 함정

문제는 Flex item의 기본 min-width에 있습니다.

Flex item의 기본 동작

Flex item의 기본값:
- min-width: auto (명시적 값이 없을 때)
- 이는 "자식 요소의 최소 콘텐츠 크기만큼은 보장한다"는 의미

즉, 아무리 overflow: hidden을 설정해도, Flex item은 자식의 콘텐츠를 다 보여주려고 늘어나버립니다.

시각적 이해

❌ min-width: auto (기본값)

부모 Container (width: 300px)
  │
  └─ Flex item (.category-post-link)
      │  min-width: auto
      │  → 자식 콘텐츠 크기에 맞춰 늘어남
      │
      └─ 자식 (.category-post-description)
          "아주아주 긴 텍스트가 계속 이어집니다..." (400px)

결과: Flex item이 400px로 늘어나서 부모를 벗어남!


✅ min-width: 0 (명시적 설정)

부모 Container (width: 300px)
  │
  └─ Flex item (.category-post-link)
      │  min-width: 0
      │  → 부모 크기를 넘지 않음
      │
      └─ 자식 (.category-post-description)
          overflow: hidden
          text-overflow: ellipsis

결과: 300px에서 말줄임 처리됨! ✨

해결 방법: 모든 Flex 단계에 min-width: 0

핵심은 텍스트가 있는 요소부터 최상위 Flex container까지 모든 단계min-width: 0을 설정하는 것입니다.

단계별 적용

/* 1. 최상위 리스트 아이템 */
.category-post-item {
  margin: 0;
  min-width: 0;  /* ✅ 추가 */
}

/* 2. Flex container인 링크 요소 */
.category-post-link {
  display: flex;
  flex-direction: column;
  /* ... */
  width: 100%;      /* ✅ 추가 */
  min-width: 0;     /* ✅ 추가 */
}

/* 3. 중간 wrapper */
.category-post-main {
  flex: 1;
  min-width: 0;     /* ✅ 추가 */
}

/* 4. 최종 텍스트 요소 */
.category-post-description {
  /* 기본 말줄임 3종 세트 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;

  /* Flex 대응 */
  min-width: 0;     /* ✅ 추가 */
  max-width: 100%;  /* ✅ 추가 */
}

왜 모든 단계에 필요할까?

Flex 레이아웃의 크기 계산 흐름:

부모 Flex container
  ↓ "자식의 min-width만큼은 보장해야지"
자식 Flex item
  ↓ "내 자식의 min-width만큼은 보장해야지"
손자 Flex item
  ↓ "내 자식(텍스트)의 콘텐츠 크기만큼은..."
텍스트

각 단계마다 min-width: auto가 연쇄적으로 작용!
→ 모든 단계에서 min-width: 0으로 끊어줘야 함

실전 예제 모음

예제 1: 카드 레이아웃

<div class="card">
  <div class="card-body">
    <h3 class="card-title">제목</h3>
    <p class="card-description">긴 설명...</p>
  </div>
</div>
.card {
  display: flex;
  flex-direction: column;
  width: 300px;
}

.card-body {
  flex: 1;
  min-width: 0;  /* ✅ */
}

.card-description {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;  /* ✅ */
}

예제 2: 가로 레이아웃 (이미지 + 텍스트)

<div class="item">
  <img src="thumb.jpg" class="item-image">
  <div class="item-content">
    <h4 class="item-title">제목</h4>
    <p class="item-description">긴 설명...</p>
  </div>
</div>
.item {
  display: flex;
  gap: 16px;
  width: 400px;
}

.item-image {
  flex-shrink: 0;
  width: 80px;
  height: 80px;
}

.item-content {
  flex: 1;
  min-width: 0;  /* ✅ 필수! */
}

.item-description {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;  /* ✅ */
}

주의: flex: 1을 쓴 요소에는 반드시 min-width: 0을 함께 써야 합니다!

예제 3: 중첩 Flex (더 복잡한 경우)

<div class="container">
  <div class="sidebar">사이드바</div>
  <div class="main">
    <div class="content">
      <h2 class="content-title">제목</h2>
      <p class="content-text">긴 텍스트...</p>
    </div>
  </div>
</div>
.container {
  display: flex;
  width: 100%;
}

.sidebar {
  flex-shrink: 0;
  width: 200px;
}

.main {
  flex: 1;
  min-width: 0;  /* ✅ 1단계 */
}

.content {
  /* 또 다른 Flex container라면 */
  display: flex;
  flex-direction: column;
  min-width: 0;  /* ✅ 2단계 */
}

.content-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;  /* ✅ 3단계 */
}

디버깅 체크리스트

말줄임이 안 될 때 순서대로 확인해보세요.

### 1단계: 기본 설정 확인
- [ ] overflow: hidden
- [ ] text-overflow: ellipsis
- [ ] white-space: nowrap

### 2단계: Flex 관련 확인
- [ ] 부모가 Flex container인가?
- [ ] 텍스트 요소에 min-width: 0 있나?
- [ ] max-width: 100% 있나?

### 3단계: 상위 요소 확인
- [ ] 모든 상위 Flex item에 min-width: 0 있나?
- [ ] flex: 1을 쓴 요소에 min-width: 0 있나?

### 4단계: width 확인
- [ ] Flex container에 명시적 width가 있나?
- [ ] 또는 부모로부터 width를 상속받나?

개발자 도구로 확인하기

Chrome DevTools에서:

1. 요소 검사로 텍스트 요소 선택
2. Computed 탭에서 확인:
   - min-width: auto → ❌ 문제!
   - min-width: 0px → ✅ 정상

3. 부모 요소도 확인:
   - 상위 Flex item들의 min-width 값 확인
   - flex: 1이 있으면 min-width도 있는지 확인

브라우저 호환성

min-width: 0은 CSS 표준이므로 모든 모던 브라우저에서 동작합니다.

/* 모든 브라우저에서 동작 */
.flex-item {
  min-width: 0;
}

/* IE11도 지원 필요하다면 */
.flex-item {
  min-width: 0;
  flex-basis: 0;  /* IE11 fallback */
}

Grid 레이아웃에서는?

Grid도 비슷한 문제가 있습니다!

/* Grid item도 min-width: 0 필요 */
.grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.grid-item {
  min-width: 0;  /* ✅ Grid에서도 필요 */
}

.grid-item-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;  /* ✅ */
}

여러 줄 말줄임은?

한 줄이 아니라 여러 줄 말줄임이 필요하다면 -webkit-line-clamp를 사용합니다.

.multi-line-ellipsis {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;  /* 2줄까지 표시 */
  overflow: hidden;

  /* Flex에서는 여전히 필요 */
  min-width: 0;
}

주의: 여러 줄 말줄임에서는 white-space: nowrap빼야 합니다!

실무 팁

1. 유틸리티 클래스 만들기

/* 한 줄 말줄임 유틸리티 */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  max-width: 100%;
}

/* Flex item 유틸리티 */
.flex-truncate {
  min-width: 0;
}

/* 사용 */
.item-content {
  flex: 1;
  /* 항상 같이 쓰기 */
}
<div class="item-content flex-truncate">
  <p class="truncate">긴 텍스트...</p>
</div>

2. Tailwind CSS 사용 시

<!-- Tailwind에서는 min-w-0 유틸리티 제공 -->
<div class="flex">
  <div class="flex-1 min-w-0">
    <p class="truncate">긴 텍스트...</p>
  </div>
</div>

3. CSS-in-JS에서 패턴화

// React + styled-components
const TruncatedText = styled.p`
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  max-width: 100%;
`;

const FlexItem = styled.div`
  flex: 1;
  min-width: 0;
`;

function Component() {
  return (
    <FlexContainer>
      <FlexItem>
        <TruncatedText>긴 텍스트...</TruncatedText>
      </FlexItem>
    </FlexContainer>
  );
}

비교표: 각 속성의 역할

속성 역할 필수 여부 적용 대상
overflow: hidden 넘치는 콘텐츠 숨김 필수 텍스트 요소
text-overflow: ellipsis ... 표시 필수 텍스트 요소
white-space: nowrap 줄바꿈 방지 필수 (한 줄) 텍스트 요소
min-width: 0 Flex 크기 제한 해제 Flex 사용 시 필수 모든 상위 Flex item
max-width: 100% 부모 초과 방지 권장 텍스트 요소
width: 100% 명시적 너비 Flex container 시 권장 Flex container

정리

핵심 원칙

Flex 레이아웃에서 텍스트 말줄임:

1. 기본 3종 세트 (텍스트 요소)
   - overflow: hidden
   - text-overflow: ellipsis
   - white-space: nowrap

2. Flex 대응 (모든 Flex item)
   - min-width: 0

3. 안전장치
   - max-width: 100%
   - width: 100% (container)

빠른 해결 템플릿

/* Flex container */
.container {
  display: flex;
  width: 100%;  /* 또는 고정값 */
}

/* 중간 Flex item (있다면) */
.flex-item {
  flex: 1;
  min-width: 0;  /* 🔑 핵심! */
}

/* 텍스트 요소 */
.text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;      /* 🔑 핵심! */
  max-width: 100%;
}

기억할 것

“Flex에서는 min-width: 0을 잊지 말자!”

  • Flex item은 기본적으로 min-width: auto
  • 이는 자식 콘텐츠 크기를 보장하려고 함
  • 텍스트 말줄임을 원하면 min-width: 0으로 해제
  • 모든 상위 Flex item에도 적용 필요

관련 이슈

비슷한 문제를 겪는 다른 상황들:

/* 1. 긴 URL이 레이아웃을 깨뜨릴 때 */
.url {
  overflow-wrap: break-word;
  word-break: break-all;
  min-width: 0;
}

/* 2. 긴 코드 블록이 넘칠 때 */
.code-block {
  overflow-x: auto;
  min-width: 0;
}

/* 3. 표 안에서 말줄임 */
td {
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

참고 자료


다음에 텍스트 말줄임이 안 될 때, “아, min-width: 0!”이라고 바로 떠올리시면 성공입니다! 😊

댓글