v149 · DOM · demo

Range Geometry Explorer

OpaqueRange spans text across shadow DOM boundaries. Create a range that crosses from the main document into a shadow root, inspect its geometry via getClientRects(), and freeze it as a CSS Custom Highlight.

Document stage

The document below has a shadow DOM component embedded inline. The range crosses the boundary.

The quick brown fox jumps over the lazy dog — this text lives in the main document.

↓ Shadow DOM component (host element)

Back in the main document: additional context follows below.

Range properties

PropertyValue
No range created yet — press "Create OpaqueRange"

Geometry panel

getClientRects() output will appear here after "Show getClientRects()"

CSS Custom Highlight freeze

When you "Convert to Static Highlight", the range is registered with the CSS Custom Highlight API. The highlight persists even if the OpaqueRange is garbage-collected.
No highlight registered yet.

How it works

  1. Create OpaqueRange — calls new OpaqueRange() (or new StaticRange() as fallback) spanning from a text node in the main document to a text node inside the shadow root.
  2. Show getClientRects() — iterates the DOMRect list returned by range.getClientRects() and draws red overlay boxes in document coordinates.
  3. Convert to Static Highlight — registers the range with CSS.highlights.set('opaque-demo', new Highlight(range)) so the browser paints the highlight independently.

Without OpaqueRange, a regular Range cannot be constructed with cross-shadow-root endpoints — it would throw or silently constrain itself to one tree.

see also