Library / SDK
xiaody/react-lines-ellipsis avatar
xiaody/react-lines-ellipsis

react-lines-ellipsis: clamping text to a fixed number of lines in React

Simple multiline ellipsis component for React.JS

653 stars78 forksJavaScriptMIT

At a glance

What is it?
react-lines-ellipsis is a small React component that truncates text to a given number of lines by measuring the rendered text in the browser, then trimming the string until it fits. It has a plain-text path, an experimental rich HTML path, a responsive higher-order component, and a loose CSS-based variant, and it states its limits plainly.
Who is it for?
react-lines-ellipsis suits a React application that needs a hard line clamp rather than a soft CSS truncation, and its measurement-based approach handles the case where the text height depends on the rendered content, which is why the project offers it alongside a loose CSS-based alternative.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 44 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A measured clamp rather than a CSS guess

The README describes the component as a poor man's multiline ellipsis component for React.JS, and the homepage is a documentation site at xiaody.github.io/react-lines-ellipsis. The approach is the interesting part. Rather than relying on a CSS truncation, the component renders the text, measures what the browser actually laid out, and then works out how much of the string fits in the allowed number of lines, trimming the remainder and appending an ellipsis. That is why there is a whole set of options around splitting and trimming rather than a single line-clamp declaration, and why the component needs a browser rather than only a server. The package is MIT licensed, published to npm as react-lines-ellipsis, built with microbundle, and its dev dependencies include enzyme and jest-adjacent tooling for the tests, with standard as the linter. The repository top level is small: a .babelrc, a snowpack.config.js for the docs site, a src/ directory, docs-src/, a CHANGELOG.md and the package manifest.

Installation and the basic usage

Installing the stable version is one command:

bash
npm install --save react-lines-ellipsis

The component is then used with a text prop and a line limit:

jsx
import LinesEllipsis from 'react-lines-ellipsis'

<LinesEllipsis
  text='long long text'
  maxLine='3'
  ellipsis='...'
  trimRight
  basedOn='letters'
/>

Note that the props in the README's own example are passed as strings, so maxLine is given as a string even though the options section types it as Number or String. The component is the default export, and the build produces a CommonJS entry point at lib/index.js and an ES module at lib/index.modern.mjs, with the type of the peer dependency left as react: * and react-dom: *, so there is no version constraint on the host application. That is a deliberate choice for a component like this one, since it renders through the standard React API and nothing else.

The options that decide how much text survives

The options list is where the component's behaviour is actually specified. props.text is the string you want to clamp. props.maxLine is the maximum count of lines allowed, defaulting to 1, and it accepts a Number or a String. props.ellipsis is the text content of the ellipsis, defaulting to a single character ellipsis, and it is typed as a Node, so you can pass an element rather than a string. props.trimRight is a boolean that trims the right of the clamped text to avoid putting the ellipsis on an empty line, and it defaults to true. props.basedOn splits by letters or by words, and by default the component uses a guess based on your text. props.component is the tagName of the rendered node, defaulting to div, which is how you get a span or a p instead. props.onReflow, available from version 0.13.0, is a callback invoked when the reflow logic completes, and it receives an object with clamped and text. The isClamped method on the instance tells you whether the text content was clamped at all.

onReflow is how you react to the clamp happening

The callback is the interesting API because it lets a component change its own layout depending on whether the text was truncated. The README's example is a class component that stores the handler on the instance and passes it through:

jsx
  handleReflow = (rleState) => {
    const {
      clamped,
      text,
    } = rleState
    // do sth...
  }

  render() {
    const text = 'lorem text'
    return (
      <LinesEllipsis
        text={text}
        onReflow={this.handleReflow}
        maxLine={3}
      />
    )
  }

The signature is given as ({ clamped: boolean, text: string }) => any, and the point of it is that clamped tells you the text was cut, while text gives you the text as it was actually rendered after trimming. A read-more link that should only appear when the text is cut, or a measurement you want to report, both hang off that one call. The presence of the callback also explains why the component has to run a reflow pass at all: it is not just truncating a string, it is reporting back the result of its own measurement.

Three variants, and what each one gives up

The library ships three builds and each trades something. The experimental HTML truncation path imports from react-lines-ellipsis/lib/html as HTMLEllipsis and takes an unsafeHTML prop instead of text. The README is careful about the trade-offs: props.ellipsis there only supports plain text and props.ellipsisHTML is the way to fully customise the ellipsis style, onReflow gives you html instead of text, and props.trimRight is not supported by HTMLEllipsis. There is also a responsive higher-order component, imported from react-lines-ellipsis/lib/responsiveHOC, which wraps the component so it responds to window resize and orientation change:

js
import LinesEllipsis from 'react-lines-ellipsis'
import responsiveHOC from 'react-lines-ellipsis/lib/responsiveHOC'

const ResponsiveEllipsis = responsiveHOC()(LinesEllipsis)
// then just use ResponsiveEllipsis

And there is a loose version, a non-standardized CSS-based solution for some webkit-based browsers, which the README says may have better render performance but can also be fragile, with a warning to test your use case:

jsx
import LinesEllipsisLoose from 'react-lines-ellipsis/lib/loose'

<LinesEllipsisLoose
  text='long long text'
  maxLine='2'
  lineHeight='16'
/>

The stated limitations, and the common issues that follow from them

The Limitations section is short and specific, and each item predicts a class of bug. The component does not clamp text on the server side or with JavaScript disabled, so a server-rendered page will show the full text and then shorten on hydration, which is a visible layout shift. It only accepts plain text by default, with lib/html.js offered as experimental rich html support. It can be fooled by some special styles, with ::first-letter and ligatures named as examples, because the measurement and the final rendering can disagree about how wide the text is. And it requires a modern browsers environment. The Common issues section then explains the two symptoms you will actually see. If you want three lines but the component sometimes gives you four, the likely cause is that your text rendering is unstable, for example a web font whose characters are fatter, a container width set dynamically, or words in the text set dynamically. If the component cuts too much or cuts nothing, the README points you at your CSS, specifically word-break and white-space, with issue links for each. For anything else, the project asks for an issue with a stackblitz reproduction link, which is a reasonable bar for a component whose behaviour depends on layout.

Where a different approach fits better

The honest comparison is with the platform's own CSS, and the README itself points at it in the loose version section, linking to a CSS Tricks article on line clamping. The difference in approach is exactly what the loose variant exists to show. A CSS clamp is declarative, costs nothing at runtime, works without JavaScript, and clamps correctly the moment the browser lays out the text, but it does not tell the application anything, it cannot report the truncated string back, and support for a real multi-line clamp with an ellipsis is not uniform across browsers, which is why the loose variant is described as non-standardized and webkit-specific. The measurement-based component inverts that trade: it needs JavaScript and a browser, it costs a reflow pass, but it gives you a callback and a way to know what was cut. A third path exists for people who need neither, which is to not truncate at all and to control the length of the data upstream. For a list of cards where the text comes from a database, that is often the better answer, and this component is at its best where the text is dynamic, the font loads late, or the content is rich enough that a fixed clamp would look wrong.

Editorial conclusion

react-lines-ellipsis suits a React application that needs a hard line clamp rather than a soft CSS truncation, and its measurement-based approach handles the case where the text height depends on the rendered content, which is why the project offers it alongside a loose CSS-based alternative. It is the wrong tool if you need the text clamped during server rendering, since the component explicitly does not clamp on the server side or with JavaScript disabled, and it is the wrong tool for rich content in production, because the HTML variant is labelled experimental and drops the trimRight behaviour. Verify first that your text renders with a stable font and a stable container width, since the documented common issue is the component sometimes returning one line too many when text rendering is unstable, and note that the last push was on 2026-09-10 with the package version at 0.16.1 and no GitHub releases.

Frequently asked questions

How do I install react-lines-ellipsis?

Run npm install --save react-lines-ellipsis to install the stable version. The package is MIT licensed and declares react and react-dom as peer dependencies with no version constraint.

What are the main props for the LinesEllipsis component?

props.text is the string to clamp, props.maxLine is the maximum number of lines and defaults to 1, props.ellipsis is the ellipsis content and defaults to a single character, props.trimRight defaults to true, props.basedOn splits by letters or words with a guess by default, and props.component sets the rendered tagName, defaulting to div.

Why does my clamped text sometimes come out as four lines instead of three?

The README says the likely cause is unstable text rendering, such as a web font whose characters are fatter, a container width set dynamically, or words in the text set dynamically. Making the font and the container width stable removes the ambiguity.

Does the component support rich HTML content?

There is an experimental path: import HTMLEllipsis from react-lines-ellipsis/lib/html and pass an unsafeHTML prop instead of text. The README notes that ellipsis there only supports plain text, props.ellipsisHTML is the way to customise it fully, and props.trimRight is not supported by HTMLEllipsis.

Can the component react to window resize and orientation change?

Yes, through the responsive higher-order component imported from react-lines-ellipsis/lib/responsiveHOC, which wraps the component so you can use the wrapped version directly.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. xiaody/react-lines-ellipsis on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/xiaody-react-lines-ellipsis.svg)](https://hysenlabs.com/projects/xiaody-react-lines-ellipsis)

Was this useful?