DEV Community

J Now
J Now

Posted on

Why shadow DOM beat iframe for inline tooltips

The iframe approach seems obvious: sandboxed, isolated, clean. I tried it first. The problem is that iframes can't inherit host-page fonts without a FOUC — you either flash unstyled content, or you hardcode a font stack and accept that your tooltip looks alien on every site with a custom typeface. On a site like Wikipedia or the NYT, that mismatch is immediately jarring.

Shadow DOM solves this differently. The extension's tooltip attaches as a shadow host, which means it's structurally isolated from the page's CSS cascade but physically in the same document. The host page's font rendering applies at the OS level, so body text in the tooltip inherits the same antialiasing and subpixel rendering as the surrounding article. No flash. No mismatch.

The tradeoff is that shadow DOM isolation isn't total. Some CSS custom properties (variables) can pierce the shadow boundary, so if the host page defines something like --background: transparent at the :root level, you need to explicitly reset inside your shadow styles. I ran into this on a few dark-mode sites where the tooltip was inheriting a near-invisible background until I added an explicit background: white block scoped to the shadow root.

The other thing iframes make hard: positioning. An absolutely-positioned iframe has to fight the host page's stacking context and overflow rules. I wanted the tooltip to anchor to cursor position, which means reading mouseup coordinates and placing a DOM node there. With shadow DOM the placement logic is just standard position: fixed math. With an iframe, you're fighting overflow: hidden on parent containers on sites you don't control.

For rabbitholes — a Chrome extension that renders inline explanations from Claude Haiku 4.5 for any text you highlight — the shadow DOM approach means the tooltip looks at home on every site, inherits correct fonts without polling, and doesn't trigger layout shifts when it appears.

Zero telemetry, Manifest V3. Requests go directly from your browser to api.anthropic.com.

https://github.com/robertnowell/rabbitholes

Top comments (0)