Capítulo 5 de 20

Chapter 5: Text Measurement with Pretext

Core Idea

Pretext can estimate wrapped text height before DOM measurement, while TanStack Virtual continues to own scrolling, range calculation, positioning, and scroll-to behavior. It is suited to text-heavy rows with predictable typography.

Key Concepts

  • prepare(): Expensive text/style preparation that should be cached by text and style inputs.
  • layout(): Width-dependent layout that should be rerun when content width changes.
  • Typography parity: Canvas inputs and CSS must agree on font, line height, whitespace, word break, and letter spacing.
  • Font readiness: Font loading can change metrics, so clear caches and call measure() after document.fonts.ready.
  • Text-only row: A row whose height is determined by wrapped text rather than media or arbitrary components.
  • Fallback: Unsupported environments need a non-Pretext estimate.
  • Sizing ownership: A row should have one authoritative sizing path.
  • Empty text: Pretext can return zero height, while the UI may still need one line height.

Code Examples

import { clearCache, layout, prepare } from '@chenglou/pretext'

const font = '14px Arial'
const lineHeight = 20
const preparedCache = new Map<string, ReturnType<typeof prepare>>()

function estimateRowHeight(row, contentWidth: number) {
  const key = `${row.id}:${font}:${row.text}`
  let prepared = preparedCache.get(key)
  if (!prepared) {
    prepared = prepare(row.text, font, { whiteSpace: 'pre-wrap', letterSpacing: 0 })
    preparedCache.set(key, prepared)
  }
  const text = layout(prepared, contentWidth, lineHeight)
  return Math.max(lineHeight, text.height) + 24
}
  • What it demonstrates: Cache text preparation, recompute width-dependent layout, and add the row's non-text space.

Key Takeaways

  1. Use Pretext only when its inputs describe the rendered text exactly.
  2. Rerun layout(), not prepare(), for ordinary width changes.
  3. Clear caches and recalculate after fonts become ready.
  4. Use measureElement or resizeItem for media and mixed-content rows.

Connects To

  • Ch 007: measure() and resizeItem() are the reset and external sizing tools.
  • Ch 012: The example combines Pretext with a chat-like React list.
  • Concept: dynamic measurement: One sizing owner prevents corrections from fighting.