line-clamp Patterns for Text Truncation: Multi-Line Ellipsis Without JavaScript
AI generated
{ }
@
CSS · Text Truncation · Cards · Layout
line-clamp Patterns for Text Truncation
multi-line ellipsis without JavaScript

line-clamp limits text blocks to a fixed number of lines and replaces excess content with an ellipsis, with no JavaScript measurement of text width whatsoever. For cards, product lists, and preview snippets, this is the most reliable way to build consistent layouts, as long as fallbacks and accessibility are considered from the start.

13 min read line-clamp · -webkit-line-clamp · ellipsis · fallbacks All modern browsers

1. Why text truncation is a recurring layout problem

Card layouts, product lists, and preview snippets share a common problem: the incoming text has an unknown, variable length, but the layout needs a consistent, predictable height. Without line-clamp, a product name that is too long or a lengthy description causes individual cards in a grid to grow taller than their neighbors, visually breaking the entire grid and making it look inconsistent.

Before line-clamp existed, developers solved this problem either with overflow: hidden and a fixed max-height, which brutally cuts off text in the middle of a line, or with JavaScript that measures the text width at runtime and manually truncates the string to a computed character count. Both approaches have significant drawbacks: pure height limiting produces ugly, half cut off letters, and the JavaScript solution is error prone across different font sizes, languages, and variable character widths.

The weakness of the JavaScript approach becomes especially clear in international projects with multiple language versions: a German product name can become significantly longer than its English counterpart due to compound words, and a hard coded character count limit that fits English either truncates German text too aggressively or not at all.

line-clamp solves this problem directly in the browser: the property limits a text block to a fixed number of lines and automatically replaces the last visible word with an ellipsis when the text does not fit within the available lines. The result is a clean truncation aligned to word boundaries that automatically adapts to any font size, any column width, and any language.

This automation is the central difference from all manual approaches: the browser knows the actually rendered character width of every glyph and can therefore determine precisely how much text fits into a given number of lines, whereas a JavaScript solution would first have to laboriously recreate this information, for example via an invisible measuring instance in the DOM.

2. line-clamp: the fundamentals

The property line-clamp limits the number of visible lines of a block element to a fixed value. For the truncation to work, three CSS properties must be set together: display: -webkit-box, or in more modern implementations simply display: block together with line-clamp, overflow: hidden so that excess text does not become visible, and line-clamp itself with the desired line count as a number value.

Without overflow: hidden, line-clamp has no visible effect at all, because the property itself only defines from which line onward to cut off, while overflow ensures that the cut off portion actually becomes invisible and the ellipsis is inserted. This combination of multiple properties is a common pitfall for developers using line-clamp for the first time, wondering why an isolated line-clamp: 3 declaration appears to do nothing.


/* Modern syntax: line-clamp works with plain block display */
.card-description {
  display: block;
  line-clamp: 3;
  overflow: hidden;
}

/* Legacy syntax still required for broader compatibility */
.card-description-legacy {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

3. From the -webkit prefix to a standard property

The history of line-clamp is unusual: the property existed for over a decade exclusively as -webkit-line-clamp, a vendor specific prefix originally intended only for WebKit based browsers. Because the feature was so useful, however, nearly every browser, including Chrome, Firefox, and Edge, adopted this prefix in addition to their own engine, so -webkit-line-clamp de facto became a universal standard, even though it was formally never defined as cross vendor in an official specification.

Only with the CSS Overflow Level 3 specification was line-clamp standardized as a regular, prefix free property that works together with display: block instead of the old -webkit-box syntax. For maximum compatibility across all currently deployed browsers, it is still advisable to declare both notations in parallel, with the more modern syntax as the last declaration so it takes precedence where supported, while older browsers continue to fall back to the WebKit variant.

This dual declaration may look redundant at first glance, but it is a proven, low risk pattern, because CSS fundamentally ignores unknown properties instead of throwing an error. A browser that does not yet know the standard syntax simply skips it and keeps the previously set legacy declaration.


/* Dual syntax for maximum compatibility across browser versions */
.excerpt {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;

  /* Standard syntax overrides where supported */
  display: block;
  line-clamp: 4;
}

4. Practical pattern: truncating card titles and descriptions

The most common use case for line-clamp is a product card or article preview with a title and short description. The title is often limited to two lines, the description to three or four lines, so that every card in a grid gets the same height, regardless of whether the incoming title or description text is short or long.

An important practical detail: the actually visible line height depends on line-height, and for a truly consistent card layout, a fixed minimum height should additionally be set on the text container, based on the maximum line count multiplied by the line height. That way the card height stays consistent even when a text is shorter than the allowed line count and therefore requires no truncation at all.

For titles that, for SEO reasons, are written to be as concise as possible, it is also worth having an editorial guideline for maximum character count, so that line-clamp truncation ideally never has to kick in and titles ideally remain fully visible, while the CSS rule serves as a safety net for exceptional cases.


/* Product card with consistent height regardless of text length */
.product-card__title {
  font-size: 1.125rem;
  line-height: 1.4;
  min-height: calc(1.4em * 2); /* reserve space for 2 lines even if shorter */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-card__description {
  font-size: 0.9375rem;
  line-height: 1.5;
  min-height: calc(1.5em * 3);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: #64748b;
}

5. Responsive line count per breakpoint

A fixed line count that fits desktop may leave too little or too much text visible on mobile devices with narrower columns, because the actual character count per line changes with column width. line-clamp can easily be embedded in media queries, so a mobile card, for instance, shows only two lines of description, while the same card in the desktop grid with a wider column can show four lines, without the layout becoming unstable.

This responsive adjustment is especially important for product lists with very different column widths between mobile and desktop views, for example a single column layout on a smartphone versus a four column grid on large screens. Without responsive line-clamp values, either too much text on mobile devices would unnecessarily stretch the card, or too little text on desktop would leave unused whitespace.

A proven approach is to maintain the line count together with its corresponding min-height in the same media query, so both values stay in sync and no discrepancy arises between the allowed line count and the reserved space, which could otherwise lead to minimally different card heights within the same breakpoint.


/* Responsive line-clamp values per breakpoint */
.product-card__description {
  -webkit-line-clamp: 2; /* mobile default: shorter columns */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (min-width: 768px) {
  .product-card__description {
    -webkit-line-clamp: 3; /* tablet: more horizontal space */
  }
}

@media (min-width: 1280px) {
  .product-card__description {
    -webkit-line-clamp: 4; /* desktop: widest columns */
  }
}

6. Accessibility: what line-clamp does NOT solve

A critical point often overlooked with line-clamp: the property only truncates the visual presentation, the full text remains present in the DOM and is read out in full by screen readers. In most cases this is even desirable, since sighted users see a truncated preview while screen reader users retain access to the complete content without any extra interaction.

It becomes problematic when the truncated text contains no indication of the truncation for screen reader users, for example when interactive elements like links disappear entirely within the truncated area. In such cases a visible "read more" link or an aria-label with the full title should be added, so all user groups can access the same content, regardless of whether they perceive the truncated or the full text visually.

A further important point: line-clamp must never be used to hide important legal or safety relevant information, such as allergen notices or contract terms, since the truncation is purely visual and does not represent a deliberate user decision to hide content.

For accessibility audits it is also worth doing a manual test with keyboard navigation enabled, to ensure that no invisible but focusable elements in the truncated area lead to a confusing navigation experience that would not be comprehensible purely visually.

7. Alternatives: line-clamp versus max-height and JavaScript

The simplest alternative to line-clamp is a fixed max-height combined with overflow: hidden, without an ellipsis. This approach works in practically every browser but cuts off text in the middle of a line, which looks considerably messier visually than a clean word boundary truncation with an ellipsis. For quick prototypes that may be sufficient, for a production ready design system line-clamp is almost always the better choice.

JavaScript based truncation libraries offer additional flexibility, such as truncating at any position within a word or more complex "show more" interactions with expand and collapse. This extra functionality comes at a cost though: extra script weight, potential layout shift while the script loads, and maintenance overhead for an external dependency where a native CSS solution would suffice.

A pragmatic rule of thumb: pure visual truncation without interaction belongs to line-clamp, as soon as users are meant to actively switch between a truncated and a full view, for example via an explicit "show more" button, additional JavaScript is needed anyway and line-clamp then only serves as the initial state before the interaction.

For projects that already use a utility first architecture like Tailwind, this logic can additionally be expressed directly as a utility class, so the line count per component is visible in the markup rather than maintained in separate CSS files. This makes it easier for developers to see at a glance which line limit is active where in the layout.

8. Limits and common pitfalls

A common pitfall is setting -webkit-line-clamp without display: -webkit-box and -webkit-box-orient: vertical. All three properties are mandatory for the legacy syntax, if one is missing, line-clamp has no visible effect at all. A second common mistake is applying line-clamp to an element with display: flex or display: grid, which can lead to conflicts in combination with the legacy -webkit-box syntax, since both display modes define the element's layout behavior fundamentally differently.

A further limit concerns nested interactive elements: if a link or button ends up entirely within the cut off area, it becomes invisible to sighted users but remains in the DOM and thus potentially keyboard focusable, which can lead to a confusing, invisible focus ring. This situation should be avoided through careful content structuring, for example by placing interactive elements outside the truncated text block.

A third, less often discussed pitfall concerns text with very long, unbroken character strings without spaces, such as URLs or long product codes. Since line-clamp is based on word boundaries, a single extremely long word can blow out the entire line before any truncation even applies. For such cases, overflow-wrap: break-word or word-break: break-all should additionally be added, so that unbroken character strings wrap correctly too.

9. Text truncation patterns compared directly

The choice between the various text truncation approaches depends on the specific use case. The following overview compares the most common patterns by robustness, accessibility, and implementation effort.

Approach Drawback Recommended pattern Benefit
Multi-line truncation max-height without ellipsis line-clamp Clean word boundary truncation with an ellipsis
Single-line truncation line-clamp: 1 (works, but overkill) text-overflow: ellipsis Simpler, native solution for one line
Browser compatibility Standard syntax only Legacy + standard in parallel Works in older and newer browsers
Consistent card height No min-height set min-height + line-clamp Same height even with short text
Full text access No access to full text Link or modal with full text Sighted users can read content in full

For most production use cases, the combination of line-clamp, a fixed min-height, and an additional link to the full text is the most robust pattern, because it ensures both layout consistency and full content access for every user group.

Teams building a component library should treat this combination as the default card text pattern, applying it consistently rather than reinventing a slightly different variant for each new card type.

10. Summary

line-clamp solves the recurring problem of variable text lengths in card layouts directly in the browser, without JavaScript measurement or brutal cutoffs in the middle of a line. The combination of display: -webkit-box, -webkit-box-orient: vertical, -webkit-line-clamp, and overflow: hidden remains worthwhile for maximum compatibility, even as the standardized line-clamp syntax with display: block becomes increasingly common.

For consistent card heights, a fixed min-height belongs alongside the truncation, and for accessibility reasons important content should never be hidden exclusively via line-clamp without offering an alternative access path to the full text. Following these rules yields a robust, low maintenance text truncation pattern with just a handful of CSS lines for practically any card layout.

For new projects it is worth defining the line-clamp pattern once as a reusable CSS class or utility, rather than re-implementing it in every component. That keeps truncation consistent project wide, and changes to the underlying logic, such as a new fallback for future browsers, only need to be maintained in one place.

Documenting this pattern alongside the design system's card component guidelines also helps future contributors understand why the extra properties are there, preventing accidental removal during a later refactor.

line-clamp Patterns for Text Truncation — the essentials at a glance

Mandatory combination

display: -webkit-box, -webkit-box-orient: vertical, -webkit-line-clamp, overflow: hidden.

Consistent height

Also set min-height, so short text does not produce a smaller card.

Accessibility

Full text stays available to screen readers, offer visible access to full content.

Responsive

Adjust line count per breakpoint to compensate for column width differences.

11. FAQ: line-clamp Patterns for Text Truncation

1What does line-clamp do?
Limits a text block to a fixed line count and replaces excess text with an ellipsis, without JavaScript.
2Why doesn't it work?
Usually display: -webkit-box, -webkit-box-orient: vertical, or overflow: hidden is missing, all three are mandatory.
3Do I still need the -webkit prefix?
For maximum compatibility yes, as a fallback alongside the newer prefix free syntax.
4Does the text stay accessible to screen readers?
Yes, only the visual presentation is truncated, the full text remains in the DOM.
5Suitable for just one line?
Technically yes, but text-overflow: ellipsis is the simpler native solution for a single line.
6How do I ensure consistent card heights?
Set a fixed min-height on the text container, computed from line count times line height.
7Does it work with display: flex?
Can conflict, when in doubt apply line-clamp on a separate inner element.
8Suitable for legal notices?
No, never hide important information exclusively via line-clamp without an alternative full text access path.
9Adjust line count responsively?
Yes, a different line count per breakpoint compensates for changing column widths.
10Most robust alternative?
max-height with overflow: hidden and no ellipsis, works everywhere but is a visually messy stopgap.