DEV Community

J Now
J Now

Posted on

Why rabbitholes uses shadow DOM instead of an iframe overlay

Building an inline tooltip for a Chrome extension forces a choice: iframe or shadow DOM. I picked shadow DOM, and the reason matters if you're building anything that has to render on arbitrary host pages.

The problem with iframes is font inheritance. An iframe is a separate document — it has no access to the host page's computed styles. If the page you're on uses a custom web font (Inter, Söhne, whatever), your iframe renders in the browser default. You can try to detect and re-inject the font declarations, but you'll almost always get a flash of unstyled content before the font loads, and on pages that load fonts conditionally or lazily, detection is unreliable. The tooltip looks like it belongs to a different product.

Shadow DOM sits inside the host document's render tree. It inherits font-family, font-size, and line-height from the cascade unless you explicitly reset them. For rabbitholes, that means the explanation tooltip renders in whatever typeface the article uses — the New Yorker tooltip looks like the New Yorker, an arXiv tooltip looks like arXiv. It reads as part of the page, not dropped on top of it.

Encapsulation still works. Shadow DOM prevents host-page CSS from leaking into the tooltip's internal structure. I scope all tooltip styles inside the shadow root, so there's no risk of a site's aggressive * { box-sizing: border-box } or reset stylesheet mangling the layout.

The one real cost: shadow DOM gives you no style isolation from the outside in for inherited properties. color, font-*, line-height cascade through the shadow boundary by design. For a tooltip that's supposed to feel native to the page, that's the behavior you want — but if you needed strict visual isolation regardless of host styles, you'd have to reset those properties explicitly inside the shadow root, which defeats the point.

For rabbitholes specifically — a tool that highlights text on any page and renders an explanation next to your cursor — the tradeoff is obvious. Native feel beats strict isolation. The tooltip should disappear into the reading experience, not announce itself.

github.com/robertnowell/rabbitholes

Top comments (0)