Preimage
Measured images for pretext. Preimage loads and measures images before layout runs — so browser reflows don't happen, text can wrap around figures whose dimensions aren't declared, and canvas/SVG/WebGL renderers get correct fit math without relying on CSS.
Demos
Each demo has per-panel Run buttons — click one side at a time to feel the click-to-layout delay. Photos are committed locally (~1-3MB PNGs) so cache-busting is honest and there's no CDN redirect chain skewing the numbers.
Masonry grid
Up to 90 photos, two grids. Left: stock <img> tags — column grows as each image decodes, every tile below shifts. Right: prepare() measures every image, a shortest-column layout commits in one pass, dominant-color placeholders hold the spot.
Editorial article with floats
Three floated figures inside flowing paragraph text. Naive HTML reflows as each figure decodes. Pretext + preimage measures up front and flows the text around the measured rects via flowColumnWithFloats.
Time to first sizing
One ~3MB local PNG loaded three ways: naive <img src>, declared width/height attrs, and prepare(). The timestamp shows when each strategy knows the dimensions.
Decode pool for canvas timelines
Sixteen ~1-3MB PNG frames scrubbable on a canvas. Left decodes on every scrub on the main thread; right warms a DecodePool up front and each scrub is a single cached-bitmap blit.
Scale — hundreds of tiles
Up to 500 cache-busted tiles, naive vs PrepareQueue + dimsOnly + IntersectionObserver. Measured panel takes header bytes for all tiles, lays out the whole grid, then full-fetches only what scrolls into view. Bytes-transferred readout shows what the library saves.
Virtual — ten thousand tiles, DOM-recycled
The chicken-and-egg of windowing: you need heights to position items, but heights come from loading them. Crank to 10k tiles — naive side opens 10k parallel fetches and the CSS column layout thrashes on every arriving image. Measured side probes dims-only, packs the full layout synchronously, and recycles ~40 DOM nodes as you scroll. Scrollbar is honest from frame one.
Manifest — build-time dimensions, instant layout
Cold prepare(url) versus recordKnownMeasurement hydrated from a preimage-manifest JSON. Same 34 photos, same cache-bust, same layout. Cold pays a network probe per URL. Hydrated resolves every prepare() synchronously from cache — layout commits in microseconds.
Stream — reserve space mid-stream
Same photo streamed to both panels under a throttle (simulates a WebSocket, AI-gen feed, or slow CDN). Left buffers every byte, builds a Blob, sets img.src, and only then knows the size — space pops in at the end. Right pipes the same stream through probeImageStream: the first chunk's header fires onDims, space reserves mid-stream, the final Blob renders into it when the stream drains.
Drop zone — Blob inputs
Drag images from your desktop. Left panel inlines them as naive <img> — each file's width is unknown until decode, so surrounding text shifts. Right panel runs prepare(file) — byte-probe on the first 4KB of the blob, ~5ms — and writes the exact width into the <img> before insert.
Chat — pretext rich-inline
A chat bubble with text, avatar icons, stickers, and photo attachments mixed inline. inlineImage turns each image into a pretext RichInlineItem with its measured width reserved as extraWidth. Drag the bubble-width slider — text rebreaks and images shuffle to new positions in one synchronous flow pass.