Truncate

.truncate

.truncate — clamping text to one line, or to N lines, with an ellipsis.

Examples

One line, and several

View “One line, and several” as

A single line that is longer than its box, so it ends in an ellipsis rather than wrapping.

Three lines of an excerpt, and then an ellipsis. The number of lines is a custom property, so there is no class per number.

<p class="truncate">A single line that is longer than its box, so it ends in an ellipsis rather than wrapping.</p>

<p class="truncate-lines" style="--truncate-lines: 3">Three lines of an excerpt, and then an ellipsis. The number of lines is a custom property, so there is no class per number.</p>

Truncation is purely visual: the whole string stays in the DOM, so a screen reader announces all of it while a sighted reader sees three words.

Fine for a preview whose full text is one interaction away; a defect for anything that is the only copy of a value.

Why it sometimes does nothing

View “Why it sometimes does nothing” as

This one truncates.

<div style="display: flex; gap: 1rem">
  <p class="truncate" style="min-inline-size: 0">This one truncates.</p>
</div>

A flex or grid child refuses to shrink below its content without min-inline-size: 0, so there is nothing to overflow and nothing truncates. It is the single most common reason this "doesn’t work".

Tokens 1

Level 2, declared on .truncate itself. Set any of them on that selector to restyle this utility without touching the skin.

Level 2 tokens declared by truncate
TokenDefault
--truncate-lines2

Variants and states

Variants

None. It is one shape, and the page does the rest.

Inside it

  • .truncate-lines

State it reads

None.

Before you ship it

What you have to do 4 requirements

  1. Truncation needs a box narrower than its text. An element that sizes to its own content never overflows, so nothing is ever clipped:
  2. A flex or grid child needs min-inline-size: 0. The automatic minimum size of a flex or grid item is its content, so it refuses to shrink and the text blows the layout wide instead of being clipped. This is the single most common reason truncation "does not work", and it does not look like a missing property — it looks like a broken layout. Both classes set it on themselves, so a .truncate that is the flex child needs nothing. If the truncated text sits inside a wrapper and the wrapper is the flex child, the wrapper needs it and nothing here can reach that element. Measured: a wrapper without it left the text 622px wide inside a 300px row, in all three engines.
  3. The element must not be inline. overflow and text-overflow do nothing on a non-replaced inline box, so .truncate on a bare <span> in running text is silently inert. Put it on a block-level element — inside a table cell that means a <div>, not a <span>.
  4. A table cell needs table-layout: fixed on the table. An auto table widens to fit its content and the clip never happens. The class goes on a block-level child of the cell, not on the <td>: a cell ignores overflow.

src/css/utilities/truncate.css · npx mostlycss add truncate