How Browsers Measure Text
- Event
- The Innovation Lab
- Overview
An interactive explorable explanation of browser text measurement — from Canvas measureText() and Intl.Segmenter to greedy line-breaking, variable-width reflow, and shrinkwrap binary search. Build intuition for the prepare/layout two-phase architecture that powers modern text-heavy applications.
- Technologies
- Text LayoutCanvas APIIntl.SegmenterInteractiveBrowser APIsPerformance

The Character
When you call ctx.measureText('A'), what do you actually get back? Most developers only use .width. But the TextMetrics object returns much more: bounding boxes, ascent, descent, and font-level boundaries that tell you exactly where the ink lands.
Notice how width and the actual bounding box rarely agree. A lowercase “g” descends below the baseline; an emoji may extend far beyond the font's reported width. When you need pixel-perfect layout, bounding boxes are what matter.
The Word
The Segmenter
The Line
Now we have segments with measured widths. Line-breaking is just arithmetic: accumulate widths left-to-right until the next segment would overflow, then break. No DOM. No canvas. Just numbers.
Greedy line-breaking: pure arithmetic over pre-measured widths.
The Resize
The prepare step is expensive — segmenting and measuring text takes real time. But it only runs once. The layout step is pure arithmetic over cached widths. How fast is “pure arithmetic”?
At scale 1, both approaches are near-instantaneous. Drag the scale to 1000 and the gap becomes dramatic: arithmetic layout stays flat while DOM measurement climbs. The prepare-once, layout-many architecture makes resize essentially free.
The Obstacle
CSS shape-outside lets text flow around static shapes. But what if the shape moves? Each overlapping line queries the shape’s actual edges at that y-position — not a bounding box. Text fills both sides of the shape at 60fps.
Each line queries the hexagon's actual edges at that y-position. Near the tips, more text fits. In the middle, less.
The Shrinkwrap
CSS fit-content sizes a container to its longest line — but that's rarely the tightest possible fit. What's the narrowest width that keeps text in exactly N lines? Because our layout function is pure arithmetic, we can binary search for the answer.
Because layout is pure arithmetic, we can binary search over container widths in microseconds.
Putting It All Together
Where This Matters
Virtualized Chat
Slack, Discord, Teams — thousands of messages that need height prediction for smooth scrolling without rendering every message to the DOM.
Document Editors
Notion, Google Docs — paginate and reflow on resize without triggering layout thrashing. Pagination requires knowing where page breaks fall before rendering.
Masonry Layouts
Pinterest, image galleries — predict card heights for positioning without rendering offscreen. Eliminates the layout shift when scrolling fast.
Collaborative Tools
Real-time reflow as collaborators edit. Text measurement that runs in a Web Worker via OffscreenCanvas — no main thread blocking.
This explorable was inspired by Cheng Lou’s pretext library, which uses the same core ideas — Intl.Segmenter, Canvas measureText, and greedy line-breaking — to do text layout without touching the DOM. It also handles edge cases we glossed over: Japanese kinsoku rules, emoji width correction, RTL bidirectional text, and sub-pixel rounding differences across browsers.
We build interfaces where the engineering matches the problem. When your application needs text measurement that the browser can’t provide natively, we know how to build it.
Start a ProjectReady to transform your engineering?
Whether you need technical leadership, enterprise development, or team optimization—let's discuss how we can help.