Shadow DOM 通过影子边界实现 DOM 查询与样式隔离,需用 attachShadow 创建影子根,样式须注入 shadowRoot 内部,仅 :host 和 ::slotted 可跨边界通信,并注意重置继承样式。

Shadow DOM 在自定义组件中实现 DOM 查询与样式隔离,核心是创建一个物理边界——影子边界(Shadow Boundary)。这个边界天然阻断外部样式穿透和跨树查询,不需要额外加类名或构建工具辅助。
用 attachShadow 创建独立影子树
调用 element.attachShadow({ mode: 'open' }) 后,该元素就拥有了自己的影子根(ShadowRoot),后续所有结构和样式都只作用于这棵内部子树。
- DOM 查询默认不跨边界:外部
document.querySelector('button')找不到 shadow 内的 button;必须用shadowRoot.querySelector('button') - 样式自动隔离:外部
button { color: red; }对 shadow 内 button 完全无效 - 推荐始终使用
mode: 'open'—— closed 模式不提升安全性,反而让调试、测试、框架集成变得困难
样式必须注入到 shadowRoot 内部才生效
不能把 <link rel="stylesheet"> 或全局 <style></style> 放在主文档里指望它影响组件;所有样式规则必须显式放进 shadowRoot。
- 最简方式:
shadowRoot.innerHTML = '<style>p{color:blue}</style> <p>文本</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/skill10962" title="Java 接口排错助手"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20dbae7c507.jpg" alt="Java 接口排错助手" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/skill10962" title="Java 接口排错助手">Java 接口排错助手</a> <p>在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。</p> </div> <a href="/xiazai/skill10962" title="Java 接口排错助手" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/c1c2c2ed740f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">Java免费学习笔记(深入)</a>”;</p>' - 更健壮方式:用
CSSStyleSheet实例 +adoptedStyleSheets,支持动态更新且避免 FOUC - 第三方 CSS(如 Font Awesome)也要内联或通过
<link>插入 shadowRoot,不能放
可控穿透:仅通过 :host 和 ::slotted 暴露定制入口
Shadow DOM 不是“黑盒”,而是“有门的盒子”。W3C 只允许两个标准伪类跨边界通信:
-
:host匹配宿主元素自身,适合控制容器级样式,例如:host([disabled]) { opacity: 0.4; } -
::slotted(p)只作用于传入<slot></slot>的顶层 light DOM 元素,且仅支持可继承属性(color、font、line-height),不支持margin或display - 避免写
::slotted(*)—— 它不可靠,也违背封装设计意图
别忘了重置继承样式
Shadow DOM 不自动清空父级样式。body 设置的 font-size、color、margin 仍会继承进来,导致表现不可控。
- 在
:host上加all: initial是稳妥起点,再显式声明需要的字体、行高、盒模型等 - 原生标签如
<h1></h1>、<button></button>依然受全局 reset.css 影响,需主动干预 - 通配符选择器(如
* { box-sizing: border-box })在 shadow 中无效,须单独加到:host或子元素上

















