layoutWithLines() and walkLineRanges() both accept a single fixed maxWidth applied to every line. layoutNextLine() lifts that restriction: you provide a width for each line individually, computed however you like before asking for the next line.
When layoutNextLine is the right tool
UselayoutNextLine when the available width changes from row to row:
- Text flowing around floated images. Lines beside the image are narrower than lines below it.
- Multi-column editorial layouts. The left column may have obstacles the right column doesn’t.
- Irregular containers. Text flowing inside a circle, a diamond, or any non-rectangular region.
- Obstacle-aware layout. Per-line slot geometry computed from polygon intersections.
layoutWithLines is simpler and slightly cheaper.
Basic usage
layoutNextLine is an iterator: each call returns the next LayoutLine starting from a cursor, or null when the paragraph is exhausted.
The LayoutCursor type
- Initialize the first line with
{ segmentIndex: 0, graphemeIndex: 0 }. - Advance by passing the previous line’s
endcursor as the nextstart. - Exhausted when
layoutNextLinereturnsnull.
prepareWithSegments. You do not need to manage the segment data directly.
Shrinkwrap: finding the minimum container width
walkLineRanges is well-suited for binary-searching the tightest container width that still fits a paragraph without breaking mid-word. After finding that width, call layoutWithLines once to get the actual lines:
walkLineRanges skips string materialization, it’s inexpensive to call repeatedly during a binary search over candidate widths. This is how the bubbles demo derives per-bubble shrinkwrap widths for a whole chat history without any DOM measurement.
Multi-column layout with a shared cursor
Theend cursor from layoutNextLine can be passed directly to the next column. This lets one continuous text stream flow across two (or more) columns without slicing the source string:
PreparedTextWithSegments handle.