# vue-clamp: text truncation primitives for Vue 3 that do the measuring for you

> vue-clamp provides clamping components for Vue 3 covering multiline text, trusted inline HTML, single-line strings with fixed affixes and configurable ellipsis placement, and wrapped item lists. The package ships as one library inside a pnpm workspace, measures text in the browser rather than guessing from string length, and comes with a migration guide because the component API changed across versions.

**Justineo/vue-clamp** — Clamping primitives for Vue.

- Repository: https://github.com/Justineo/vue-clamp
- Website: https://vue-clamp.void.app
- Stars: 842 · Forks: 94
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/justineo-vue-clamp

## What the package covers and why it exists

vue-clamp provides clamping primitives for Vue 3. The README describes it as including components for multiline text, trusted inline HTML, single-line strings with fixed affixes and configurable ellipsis placement, and wrapped item lists.

That list is more specific than the phrase text truncation, and the differences matter.

Multiline text clamping is the case where a fixed number of lines is not enough, because a paragraph truncated at a character count ends mid-word and looks broken. A component that measures the rendered text can truncate at a word boundary and keep the last line's worth of content visible.

Trusted inline HTML is the case that rules out the naive approaches. If your text contains markup, a character count is meaningless because the tags count too, and a naive substring cut can slice a tag in half. A component that works on the rendered DOM can truncate after the visible content rather than the source string.

Single-line strings with fixed affixes covers the pattern where a value has a currency symbol or a unit that must stay visible: the affix takes its space and the variable part is what gets clamped, with the ellipsis placed where you want it rather than always at the end.

And wrapped item lists is the case of a tag list or a breadcrumb that has to fit one line, where each item is a unit and the truncation should fall between items rather than through one.

The repository is MIT licensed, the default branch is main, and the last push was on 2026-10-19, with releases v1.7.2 from 2026-09-28, v1.7.1 from 2026-09-11 and v1.7.0 from 2026-09-09. The site is at vue-clamp.void.app and the topics are clamp, line-clamp, text-truncation and vue.

## How the package is structured and what the workspace holds

The repository is a pnpm workspace with two packages listed in the README.

packages/vue-clamp is the published vue-clamp library, and packages/website is the documentation and demo site. The package README lives at packages/vue-clamp/README.md, and the site is the vue-clamp.void.app domain.

There are three documents beyond the README that a user will need at some point: a MIGRATION.md, a CHANGELOG.md for release notes, and the package-level README. The presence of a migration guide at the top level is the notable one, and it tells you the component API has changed between versions.

The top-level listing shows a working setup rather than a single package: a scripts/ directory, a tools/ directory, a tests/ directory, a journey/ directory, assets/, .vite-hooks/, .vscode/ and an AGENTS.md. The Vite hooks directory suggests the build is extended at the Vite level, and the AGENTS.md is the same convention of machine-readable contributor guidance seen in several other projects in this workspace.

There are two TypeScript configuration files for the browser tests, vite.browser.config.ts and vite.browser.benchmark.config.ts, separate from the main vite.config.ts, which tells you that the browser test environment is configured separately from the package build rather than sharing one config.

The root package.json is the workspace manifest. Its name is vue-clamp-workspace and its version is 0.0.0, with private set to true, which is the convention for a workspace root that is never published. The publishable version lives in packages/vue-clamp/package.json, and the release script bumps it there with bumpp rather than touching the root.

Dependency versions are managed through catalog references, with every devDependency given as catalog:, and there is a renovate.json at the root for automated updates.

## The development workflow and the benchmark harness

The workspace uses Vite+ and the README says to run project tasks through vp. The commands are short.

Installation is a single command:

```bash
vp install
```

The full local readiness check is:

```bash
vp run ready
```

And the common commands are:

```bash
vp check
vp test
vp run test:browser
vp run build
vp run website#dev
```

The readiness script in the root package.json shows what that check comprises: it runs the check task, the test task, the browser test and the build, in that order. So the readiness command is not a smoke test, it is the whole gate, and a contributor runs it before pushing.

The benchmark side is more elaborate than a typical library's, and it is where the measurement claim lives. There are benchmark scripts for the package itself, with a smoke mode, a strict mode and a compare mode, and separate benchmarks for pretext handling, for rich content, for the source and for wrapping. The pretext benchmarks are named pretext, matrix and size, and the size one runs the package build first and then measures.

The environment variable VUE_CLAMP_BENCH_MODE selects between smoke and strict, which is a reasonable pattern for a benchmark that has to run both quickly in continuous integration and thoroughly on demand.

The browser tests run under Playwright through the vitest browser mode, with separate configurations for tests and for benchmarks. That is the right choice for a library whose whole job depends on layout: a text measurement library cannot be verified in a Node environment, because there is no layout there.

## Limits: a versioned API, measured behaviour and trusted content

Several limits are worth being concrete about.

The first is the API versioning. The existence of MIGRATION.md at the root, alongside a CHANGELOG.md and releases arriving roughly every two weeks across v1.7.0, v1.7.1 and v1.7.2, tells you the component API has moved. Anyone upgrading has to read the migration guide, and the fact that the README points to it separately from the package README suggests it is not optional reading.

The second is that a measurement-based component behaves differently from a CSS one in ways that matter. A component that measures the rendered text and truncates it has to re-measure when the font loads, when the container resizes, when the content changes and when a translation produces longer words. The benefit is correct truncation with affixes and real markup; the cost is a component in your render tree that has to keep its measurement current, and a layout that is one resize observer away from a different result.

The third is the trust requirement in the inline HTML component. The README describes it as trusted inline HTML, and the word is doing real work: a component that renders markup rather than text will interpret it, so it belongs with content you already trust. Passing user-submitted HTML through it would be a script injection route, and that is a decision to make deliberately rather than by default.

The fourth is that this is a text-only library. It does not clamp images, it does not handle a single overflowing flex child the way a CSS min-width: 0 does, and it does not give you a virtualised list. If your truncation problem is a layout problem rather than a measurement problem, the browser's own line-clamp and text-overflow properties are usually enough and cost nothing.

The fifth is the dependency floor. The root package.json requires node ^22.18.0 or a newer supported line, which is a recent floor, and the workspace targets modern Vite with Vue macros and an unplugin-based Vue setup, so integrating it into an older build is not a drop-in.

## This library against the CSS line-clamp and against writing your own measurement

Two comparisons make the choice clearer.

The first is against the CSS line-clamp property and text-overflow with an ellipsis. The difference in approach is that the browser does the measurement natively and instantly, with no JavaScript and no component in your tree. That is better in almost every case where it applies, and it is free. What CSS cannot do is clamp to a word boundary, keep a fixed affix visible, truncate an element containing markup without slicing a tag, or fall back between items in a wrapped list. Those four cases are the library's reason to exist, and they are real problems that come up in product interfaces.

The cost of the library in those cases is that you give up the native path and take on a JavaScript component that measures and re-renders. For a list of a few hundred items that is a real cost, and the library's own benchmark harness exists because the author was measuring exactly this.

The second comparison is against writing your own measurement. It is not hard: render the text into a hidden element, read scrollHeight, compare against the container height, and truncate. The trouble is in the details that have to be right. You need to re-measure when the font loads, because the fallback font has different metrics and your truncation points are computed from the wrong text. You need to handle the case where a single word is longer than the container. You need to not truncate markup. And you need the affix handling, where the fixed part of the string is measured and removed from the available width.

Each of those is an afternoon, and each is a bug that only shows up in some font, some locale or some content. The library is the accumulated result of that work, which is what a small focused library with a benchmark suite and a migration guide actually represents.

So the practical rule is simple. If CSS can do it, use CSS. If you need word-boundary truncation, affixes, markup safety or item-level clamping, this is a well-tested answer rather than something to reinvent inside your design system.

## Conclusion

Adopt vue-clamp when you need text truncation that respects affixes, real inline HTML and wrapped lists, and you want the measurement done in the browser rather than approximated from character counts. Do not adopt it for plain single-line CSS ellipsis, which one line of text-overflow handles. Verify first which component API your version exposes, since the migration guide exists because the API changed, and check that your content is trusted before using the inline HTML component, since it renders markup rather than text.

## FAQ

### What does vue-clamp provide?

Clamping primitives for Vue 3, with components for multiline text, trusted inline HTML, single-line strings with fixed affixes and configurable ellipsis placement, and wrapped item lists. The topics line the package under clamp, line-clamp, text-truncation and vue.

### How is vue-clamp developed and tested?

The workspace uses Vite+ and tasks run through vp. Install with vp install and run the full local readiness check with vp run ready, which covers the check task, the tests, the browser tests and the build. Browser tests run under Playwright through vitest browser mode with a separate configuration from the package build.

### What is the structure of the vue-clamp repository?

It is a pnpm workspace with two packages: packages/vue-clamp, which is the published library, and packages/website, the documentation and demo site. The root package.json is the private workspace manifest with version 0.0.0 and a release script that bumps the version in packages/vue-clamp/package.json, alongside a MIGRATION.md, a CHANGELOG.md and a package-level README.

## Sources

- [Justineo/vue-clamp on GitHub](https://github.com/Justineo/vue-clamp)
- [License: MIT](https://github.com/Justineo/vue-clamp/blob/main/LICENSE)
- [Project website](https://vue-clamp.void.app)
- [README](https://github.com/Justineo/vue-clamp/blob/main/README.md)
- [Releases](https://github.com/Justineo/vue-clamp/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/justineo-vue-clamp
