Line Clamp

Free

Text truncation using CSS line-clamp with ResizeObserver overflow detection, an optional gradient fade and an animated Show more / Show less toggle.

</>sv-line-clamp truncatetextclamp

Complexity tier: Primitive Presents a value: held to semantic markup and contrast, with its right-to-left and print gaps recorded and the right-to-left debt allowed only to shrink.

import { SvLineClampComponent } from '@styloviz/display';

Demo & usage

Basic usage

Usage example — open the gallery for the full interactive demo.

An interactive demo for this component lives in the gallery.

Open live demo

More examples

Fade with no toggle

example.htmlAngular
<sv-line-clamp [lines]="2" [fadeOut]="true" [showToggle]="false">{{ summary }}</sv-line-clamp>

Controlled expansion

example.htmlAngular
<sv-line-clamp [lines]="3" [(expanded)]="isOpen">{{ body }}</sv-line-clamp>

Links inside clamped text

line-clamp CLIPS; it does not remove. A link on line eight of a three-line clamp is still in the tab order and drawn nowhere the user can see, so tabbing through the page appears to swallow focus. Focus landing below the clamp line opens the block, and leaving it closes it again — unless the reader took it over by pressing the toggle. Not inert: there is no element boundary between the shown lines and the clipped ones, so inert on the box would take the visible text out of the accessibility tree as well.

example.htmlAngular
<sv-line-clamp [lines]="3">
  Read the <a href="/policy">full policy</a> before continuing.
</sv-line-clamp>

<!-- Or turn it off and keep focusables out of clamped text yourself: -->
<sv-line-clamp [lines]="3" [expandOnFocus]="false">{{ plainText }}</sv-line-clamp>

Printing

Paper has no "Show more". A clamped block used to print exactly as it looked on screen — three lines and a fade — and a printed clause that stops mid-sentence is indistinguishable from one that ended there. The component now unclamps under @media print and hides the fade and the toggle. Nothing to configure; it is in the component stylesheet.

example.htmlAngular
<!-- Prints in full, expanded or not. -->
<sv-line-clamp [lines]="3">{{ incidentNote }}</sv-line-clamp>

When to use

  • Truncating long text to a fixed number of lines with an optional expand toggle.
  • Card descriptions, comments, table cells where vertical space is constrained.
  • For collapsing arbitrary content (not just text), use Expand / Collapse.

Async states

None — this component has nothing to load, so it has no loading, empty or error state to drive.

Inputs

NameTypeDefaultDescription
linesnumber3Number of lines to clamp to.
expandLabelstring'Show more'Label for the expand button.
collapseLabelstring'Show less'Label for the collapse button.
showTogglebooleantrueShow the toggle button when overflowing.
fadeOutbooleantrueShow a gradient fade at the truncation edge.
expandOnFocusbooleantrueExpand when focus reaches something clipped out of view.
expandedboolean (two-way)falseExpanded state. Two-way bindable (`[(expanded)]`) so the host can read or drive it; the matching `expandedChange` output fires on every toggle.

Outputs

EventPayload typeDescription
expandedChangebooleanEmits the new `expanded` whenever it changes — the output half of `[(expanded)]`.

Customization & theming

  • Set the visible line count with `lines` and add a `fadeOut` gradient.
  • Toggle expansion with `showToggle` and relabel via `expandLabel` / `collapseLabel`.
  • Two-way bind `[(expanded)]` to control or read the state, or listen to `expandedChange`.
  • `expandOnFocus` (on by default) opens the block when focus reaches something clipped out of view, and closes it again when focus leaves — unless the reader pressed the toggle themselves, which takes ownership.
  • Printing unclamps the text and drops the fade and the toggle. It lives in the component stylesheet under `@media print`, so there is nothing to bind.

Best practices

  • Do: Keep the full text in the DOM (it is) so search and screen readers see it.
  • Do: Show the toggle only when the text actually overflows — it detects this for you.
  • Tip: Use `fadeOut` for a softer cutoff when no toggle is shown.
  • Don't: Don't clamp text whose meaning depends on the end — a total, a deadline, a negation. The clamp point moves with the container width, so what survives is not something you chose.
  • Tip: Leave `expandOnFocus` on if the text can contain links or buttons. Turn it off only when you can guarantee it cannot.

Accessibility

  • The toggle is a labelled button that reflects expanded state via `aria-expanded` and points at the text region with `aria-controls`.
  • Full text remains in the DOM for screen readers and search.
  • Overflow is detected so the toggle only appears when needed.
  • A focusable element clipped by the clamp is not left as an invisible tab stop: focus landing below the clamp line expands the block, so the focus ring is always drawn somewhere the user can see. `inert` was rejected — there is no element boundary between the shown and clipped lines, so it would remove the visible text from the accessibility tree too.
  • Printed output is unclamped, and the fade and toggle are hidden — a printed page cannot follow a "Show more".

Feedback on Line Clamp

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.