How Shadow DOM Keeps Imported HTML Isolated
Understand style boundaries, event behavior, focus, and the tradeoffs of rendering third-party HTML inside a shadow root.
The short version
Shadow DOM is a style and DOM boundary, not a complete security boundary.
Use the boundary for predictable rendering
A shadow root prevents most page styles from leaking into an imported document and prevents imported selectors from casually restyling the host interface. That makes arbitrary HTML more predictable inside an editor.
The host can inject a controlled stylesheet and then place the imported shell inside the root. CSS custom properties can intentionally cross the boundary when theming is required.
const host = document.querySelector('[data-document-host]')
const root = host.attachShadow({ mode: 'open' })
const style = document.createElement('style')
style.textContent = ':host { display: block } img { max-width: 100% }'
root.append(style, documentFragment)Plan for focus and events
Events can cross the shadow boundary with a retargeted event target. Focus, selection, and query logic need explicit handling because document-wide utilities may not see inside the root.
Know what Shadow DOM does not solve
- It does not sanitize scripts or dangerous URLs.
- It does not prevent network requests.
- It does not replace a Content Security Policy.
- It does not automatically make custom controls accessible.
- Closed mode is not a strong security guarantee.