Shadow DOM已废弃/deep/等深度选择器,Chrome 120+/Firefox 115+彻底移除;仅保留:host和::slotted()两个标准穿透方式,分别用于控制宿主自身状态和投影内容的可继承样式。

Shadow DOM 没有“深度选择器”这个东西,/deep/、::ng-deep、>>> 全部已被主流浏览器废弃——Chrome 120+ 和 Firefox 115+ 已彻底移除支持,继续用等于放弃兼容性。
为什么 /deep/ 现在完全不能用了
它不是“失效”,是被规范删除了。浏览器解析样式时直接跳过含 /deep/ 的整条规则,连警告都不报。你写 .host /deep/ .inner { color: red; },等于这行 CSS 不存在。
- 历史定位:它本是 Web Components 草案阶段的临时穿透方案,从未进入正式 CSS 标准
- 现实表现:DevTools 里查不到匹配,
getComputedStyle()返回原始值,Safari 从没实现过 - 替代路径:W3C 明确只保留
:host和::slotted()两个合法出口
:host 是唯一能影响宿主自身状态的入口
它只作用于自定义元素标签本身(即 <my-button></my-button> 这个节点),不匹配其内部子树。
-
:host { display: inline-block; }—— 控制组件容器显示方式 -
:host([disabled]) { opacity: 0.4; }—— 响应宿主属性变化 -
:host(.theme-dark) .label { color: #eee; }—— 结合宿主 class 控制内部可继承样式 - 禁止写
:host div { ... }—— 这种后代选择器在 Shadow DOM 中无效,浏览器不计算
::slotted() 只透传可继承样式,且仅限顶层 slot 内容
它匹配的是被 <slot></slot> 投影进来的 light DOM 节点,且只允许设置 color、font、line-height、background-color 等可继承属性。
立即学习“前端免费学习笔记(深入)”;
-
::slotted(p) { line-height: 1.6; }—— 合法,p是 slot 直接子节点 -
::slotted(*) { margin: 0; }—— 不推荐,破坏封装,且margin属于不可继承属性,会被忽略 -
::slotted(.item > span) { ... }—— 无效,::slotted()不支持嵌套选择器 - 若 slot 里传入的是
<div><p>xxx</p></div>,::slotted(p)仍能命中,但::slotted(div p)不行
动态注入第三方 CSS 的实际可行路径
想让 Font Awesome 或 Tailwind 类名在 Shadow DOM 里生效,不能靠 <link rel="stylesheet"> 直接塞进去——那样加载到全局,失去隔离意义。
- 必须用
CSSStyleSheet实例 +adoptedStyleSheets:Chrome 73+/Safari 16.4+ 支持 - 对
@import和相对路径(如url(./icon.svg))要提前做资源代理或内联替换 - 避免用
shadowRoot.innerHTML = '<style>...</style>'—— 会销毁旧<style></style>,触发 FOUC - 若需兼容老版本,只能将第三方 CSS 提前转为字符串,再通过
document.createElement('style')注入
真正难的不是语法,而是接受「没有万能穿透」这个事实:Shadow DOM 的边界不是漏洞,是协议。越想绕过,越容易掉进样式断裂、FOUC、调试失能的坑里。



















