truncate와 line-clamp, 말줄임이 안 먹을 때 뭘 봐야 할까?

truncate와 line-clamp, 말줄임이 안 먹을 때 뭘 봐야 할까?

June 26, 2026

Style

line-clamp-1을 붙였는데 텍스트가 안 잘립니다. 콘솔에 에러도 없고, 개발자 도구로 열어보면 클래스도 얌전히 붙어 있습니다. 그런데 은 끝내 안 나옵니다.

저는 이 상황에서 한참을 헤맸습니다. 원인은 바로 옆에 붙어 있던 flex 한 줄이었는데, 그걸 알고 나니 truncateline-clamp이 왜 다르게 동작하는지가 같이 풀렸습니다.

두 유틸이 어떻게 다른지, 그리고 말줄임이 소리 없이 안 먹을 때 어디부터 봐야 하는지 적어 봤습니다.

이름은 비슷한데 기반이 다릅니다

둘 다 넘치는 텍스트를 로 줄여 주니 비슷해 보이지만, 실제로 생성되는 CSS를 나란히 놓으면 기반이 다릅니다.

/* truncate */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* line-clamp-1 */
.line-clamp-1 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
}

truncatewhite-space: nowrap으로 줄바꿈을 막고, 넘치는 부분을 text-overflow: ellipsis로 자릅니다. 한 줄 전용이고 display는 건드리지 않습니다.

line-clamp은 여러 줄을 자를 수 있는 대신, display: -webkit-box라는 옛날 webkit 박스 모델 위에서만 동작합니다. N줄 말줄임 자체가 그 위에 얹혀 구현돼 있기 때문입니다.

한 줄(line-clamp-1)도 되긴 하지만, 이걸 쓰는 순간 그 엘리먼트의 display를 가져간다는 게 핵심입니다.

webkit 박스 모델(-webkit-box)이란?
지금 쓰는 display: flex가 표준이 되기 전, 2009년경 webkit이 먼저 구현한 1세대 플렉스 레이아웃입니다. 표준에서는 밀려났지만 -webkit-line-clamp(여러 줄 말줄임)이 이 박스 모델 위에 얹혀 있어서, 지금도 N줄 말줄임을 쓰려면 display: -webkit-box를 함께 선언해야 합니다. 표준은 아니지만 모든 주요 브라우저가 지원합니다.

truncateline-clamp-N
줄 수한 줄만N줄 (1줄 포함)
핵심 속성white-space: nowrap + text-overflowdisplay: -webkit-box + -webkit-line-clamp
display 점유안 함함 (-webkit-box)
동작 기반블록 안 인라인 텍스트webkit 박스 모델

한 줄이면 둘 다 됩니다. 하지만 여러 줄을 자르려면 line-clamp뿐이고, 그 대가로 display를 내줘야 합니다. 제가 헤맸던 지점이 바로 이 대목이었습니다.

안 잘리면 같은 엘리먼트의 display부터 봅니다

제 경우가 딱 이랬습니다. line-clampflex를 같은 엘리먼트에 얹은 것입니다.

<span className="... flex items-center line-clamp-1">{label}</span>

세로 중앙 정렬이 필요해서 flex items-center를 붙였고, 말줄임이 필요해서 line-clamp-1을 붙였습니다. 둘 다 흔한 유틸이라 의심조차 안 했는데, line-clamp-1은 조용히 무시되고 있었습니다.

flexdisplay: flex를, line-clampdisplay: -webkit-box를 선언합니다. display는 값이 하나뿐이라, 최종 스타일시트에서 뒤에 오는 선언만 살아남습니다. -webkit-box가 밀려나면 line-clamp은 기댈 기반이 없어 조용히 무력화됩니다.

충돌이라기보다 같은 display를 다른 값으로 덮어쓴 것에 가깝습니다.

flowchart TD
    A["한 엘리먼트에 line-clamp + flex"] --> B["line-clamp → display: -webkit-box"]
    A --> C["flex → display: flex"]
    B --> D["display 값은 하나뿐, 뒤 선언이 이김"]
    C --> D
    D --> E["-webkit-box 제거 → 말줄임 무력화"]

truncate로 바꿔도 flex 컨테이너에 직접 주면 마찬가지입니다. text-overflow: ellipsis는 블록 안에서 넘치는 인라인 텍스트를 자르는데, display: flex가 되면 자식이 flex item으로 배치되어 애초에 ellipsis 적용 대상에서 빠집니다.

그래서 말줄임이 안 먹을 때 저는 같은 엘리먼트에 display를 바꾸는 다른 유틸이 있는지부터 봅니다. flex, grid가 대표적입니다.

레이어를 나누면 풀립니다

원인이 “한 엘리먼트가 display를 두 용도로 못 쓴다”는 것이라면, 해결도 거기서 나옵니다. 바깥과 안쪽 두 레이어로 역할을 나누면 됩니다. 바깥은 레이아웃을 맡고, 안쪽 별도 span이 말줄임을 맡습니다.

<span className="... flex items-center min-w-0">
  <span className="truncate" title={label}>
    {label}
  </span>
</span>
  • 바깥 span은 flex items-center로 세로 중앙 정렬을 맡습니다.
  • 안쪽 span은 truncate로 말줄임을, title로 hover 시 전체 텍스트를 맡습니다.

display를 두고 다투던 두 역할이 서로 다른 엘리먼트로 갈라지니, 경합할 일이 없어집니다.

그런데 여기서 한 가지를 더 봐야 하는데, flex item의 최소 너비입니다. flex item은 기본값이 min-width: auto라 콘텐츠의 min-content 아래로는 줄어들지 않아서, 긴 텍스트가 셀을 무시하고 밀고 나가 애초에 넘침(overflow) 자체가 안 생기기도 합니다.

푸는 방법은 둘입니다.

  1. 바깥에 min-w-0(min-width: 0)을 줘서 줄어들 수 있게 합니다.
  2. 스펙상 flex item의 overflowvisible이 아니면 자동 최소 너비가 0이 됩니다(CSS Flexbox §4.5). truncate에는 overflow: hidden이 들어 있으니, 안쪽 truncate span 자체가 이미 이 조건을 충족합니다.

즉 위 코드는 안쪽 truncate만으로도 동작하고, 바깥 min-w-0은 없어도 됩니다. 다만 구조가 조금만 복잡해져도 어디서 너비가 안 줄어드는지 추적하기 번거로워서, 저는 방어적으로 바깥에 min-w-0을 같이 두는 편입니다.

  • truncate
  • line-clamp
  • Tailwind 말줄임
  • text-overflow ellipsis
  • -webkit-box
  • display flex 충돌
  • flex item min-width
  • min-w-0
  • CSS 말줄임
On this page