v137 · dom

Text Annotator

Select any text — including across the dashed shadow DOM inline components — choose a highlight colour, and the annotation is applied via getComposedRanges(). Without composed ranges, a selection crossing a shadow boundary would return an empty range from getRangeAt(0).

Feature detection: checking…
Highlight:

Select text (including across the dashed shadow-DOM spans) and click a colour. The document contains three inline components in open shadow roots — try selecting across their boundaries.

Research Document

The CSS Dynamic Range Limit property lets authors control the maximum brightness of HDR content. Published in by the CSS Color HDR working group, it introduces three values: standard, constrained-high, and high.

When compositing images alongside text, the property is inherited, meaning a single rule on a container cascades to all children. The recommended pattern from suggests setting standard on body and overriding selectively on image elements.

In practice, the approach requires no JavaScript — the CSS cascade handles everything. HDR-capable displays respond immediately; SDR panels tone-map at the compositor, making the property a safe progressive enhancement.

Select text above to see composed range details…
Annotations (0)
No annotations yet
// getComposedRanges() crosses shadow DOM boundaries
document.addEventListener('selectionchange', () => {
  const sel = window.getSelection();
  if (!sel.getComposedRanges) return;

  const ranges = sel.getComposedRanges({ shadowRoots: openRoots });
  if (!ranges.length) return;

  const range = ranges[0];
  console.log('direction:', sel.direction);
  console.log('start:', range.startContainer, range.startOffset);
  console.log('end:',   range.endContainer,   range.endOffset);
});

// Apply highlight using the composed range
function highlight(color) {
  const ranges = sel.getComposedRanges({ shadowRoots: openRoots });
  if (!ranges[0]?.toString()) return;
  const mark = document.createElement('mark');
  mark.style.background = color;
  ranges[0].surroundContents(mark);  // works across shadow boundaries
}

see also