v149 · Web APIs · DOM
OpaqueRange
Chrome 149 adds element.createValueRange(start, end) to <input> and <textarea> elements — a live range object that exposes geometry (bounding rects) for a span of the control's value text, without leaking the internal DOM.
concepts
-
Geometry Inspector
Select text inside a
<textarea>and watchcreateValueRange().getBoundingClientRect()report the pixel position in real time — visualised as an overlay rectangle that follows your selection. -
Word Tooltip
Click any word in a text field to see a positioned tooltip anchored precisely over that word using
OpaqueRangegeometry — the kind of inline suggestion or annotation UI that previously required fragile hacks. -
Inline Annotation
Select any text span in the editor, add a note, and hover the annotation list to see the tooltip appear exactly over that phrase — all positioned using
createValueRange().getBoundingClientRect(). Demonstrates a real-world annotation workflow. -
Selection Bounds
Live canvas overlay that tracks your text selection in real time using
createValueRange(selectionStart, selectionEnd). Toggle between the single bounding rect and the per-line client rects to see exactly how multi-line selections decompose into individual rectangles. -
Spellcheck Overlay
Custom spellcheck that draws wavy, straight, or dotted underlines directly beneath misspelled words using
getClientRects()geometry. Shows how to build inline error indicators without touching the DOM inside the form control. -
Range Geometry Explorer
Interactive explorer of all
OpaqueRangegeometry APIs. Select a region, then comparegetBoundingClientRect()vsgetClientRects()outputs as animated overlays. Includes a multi-line selection decomposition view and a live coordinate readout showing how cross-line selections split into per-line rectangles.
why it shipped
Before Chrome 149, there was no way to obtain the pixel coordinates of a span of text inside a form control. You could call getBoundingClientRect() on the element itself, but not on a substring of its value. This blocked rich editor UIs from positioning inline popovers, suggestions, spell-check tooltips, and annotation anchors precisely over the typed text. OpaqueRange closes that gap: createValueRange(start, end) returns a live object that exposes getBoundingClientRect() and getClientRects() for any character slice. It is deliberately "opaque" — startContainer and endContainer are always null to preserve the encapsulation of the internal shadow DOM — so the geometry is available without breaking form-control security boundaries.