Shadow DOM 通过隔离 DOM 子树实现样式封装,内部样式不泄露、外部样式不穿透;推荐内联 ,慎用 !important 和全局选择器,善用 :host、::slotted 和 CSS 自定义属性实现可控定制。

Shadow DOM 通过创建一个独立的、与主文档隔离的 DOM 子树,天然隔绝了样式作用域。它让组件内部的 CSS 不会泄露到外部,外部样式也默认无法穿透影响内部元素——这是避免样式冲突最根本的机制。
启用 Shadow DOM 并挂载样式
用 element.attachShadow({ mode: 'open' }) 创建 shadow root 后,直接向其中插入 标签或链接外部样式表即可。这些样式只对 shadow 内部节点生效,完全不参与全局样式层叠。
- 推荐内联
:简洁、无请求开销,且能配合 JS 动态生成 - 避免用
@import:性能差,且部分浏览器中在 shadow 中支持不稳定 - 若用外部 CSS,需用
插入 shadow root,而非 document.head
外部样式无法穿透,但有可控例外
默认情况下,document 中定义的类名、标签选择器、ID 等对 shadow 内部元素完全无效。不过可通过两个明确机制实现有限通信:
- ::slotted():匹配传入的 slot 内容(即 light DOM 中被投射进来的节点),可对其设置基础样式,但不能修改其内部结构
- :host 和 :host-context():在 shadow 内部定义,用于根据宿主元素自身状态(如 class、属性)或其祖先上下文调整内部样式
避免意外泄漏的实用细节
即使用了 Shadow DOM,仍可能因疏忽导致封装失效:
- 不要在 shadow 外部用
!important强行覆盖 shadow 内样式——它无效;但若在 shadow 内部滥用!important,反而会阻碍自定义(比如用户想用:host覆盖时) - 慎用 CSS 自定义属性(
--my-color):它们默认可继承,可在 shadow 内监听并响应,是推荐的“样式接口”方式 - 避免在 shadow 内使用全局选择器如
body、html或*[data-theme]——它们不会匹配到外部真实节点,易引发误判
Shadow DOM 的样式封装不是靠“禁止”,而是靠“隔离”。理解它的边界在哪里,再合理使用 :host、::slotted 和 CSS 变量,就能既保证健壮性,又保留足够的定制灵活性。










