Tight Multiline Shrink-Wrap
Compute the tightest bounding box for wrapped text — no trial-and-error needed.
Shrink-wrapping multiline text to its tightest possible width is surprisingly awkward with CSS alone. Pretext gives you the exact widest line width, so you can snap the container to a perfect tight fit.
prepareWithSegments()layoutWithLines() What this demonstrates
Using layoutWithLines() to get individual line widths, then computing the
tightest bounding box. The "Snap to tight fit" button sets the container width to the
widest line — a clean, computed value instead of a guess.
Relevant Pretext API
prepareWithSegments(text, font)— richer prepare for line-level datalayoutWithLines(prepared, maxWidth, lineHeight)— returns lines with widths
Why this is hard with the DOM
CSS width: fit-content exists but does not tightly wrap multiline text.
Getting the widest line width requires rendering, reading Range or
getClientRects(), and measuring — a fragile, slow process.
Pretext gives you the answer directly.
Quick start
import { prepareWithSegments, layoutWithLines } from '@chenglou/pretext';
// Use prepareWithSegments (not prepare) to get line-level data.
// layoutWithLines returns individual lines with their pixel widths.
const fontSize = 20;
const lineHeight = fontSize * 1.5; // 30px
const maxWidth = 500;
const font = `${fontSize}px Inter, sans-serif`;
const prepared = prepareWithSegments(text, font);
const result = layoutWithLines(prepared, maxWidth, lineHeight);
// result.lines is an array — each line has .text and .width.
// Extract per-line widths to find the widest line.
const lineWidths: number[] = [];
let widestLineWidth = 0;
for (const line of result.lines) {
lineWidths.push(Math.round(line.width));
if (line.width > widestLineWidth) {
widestLineWidth = line.width;
}
}
// The tight width is the widest line — this is the minimum
// container width that preserves the same line breaks.
const tightWidth = Math.ceil(widestLineWidth);
const spaceSaved = maxWidth - tightWidth;
console.log(`Lines: ${result.lineCount}`);
console.log(`Max width: ${maxWidth}px`);
console.log(`Widest line: ${tightWidth}px`);
console.log(`Space saved: ${spaceSaved}px`);
console.log(`Per-line widths: ${lineWidths.join(', ')}`);
// Apply the tight fit — snaps container to exact content width.
// CSS fit-content does NOT do this for multiline text.
container.style.width = (tightWidth + 2) + 'px'; // +2 for subpixel safety
// Toggle between loose and tight:
let isTight = false;
function toggleTight() {
isTight = !isTight;
container.style.width = isTight
? (tightWidth + 2) + 'px'
: maxWidth + 'px';
}