attachshadow() 仅创建影子根,样式隔离需显式注入 style 或 cssstylesheet;innerhtml 中的 不生效,因不进入 cssom;closed 模式下 shadowroot 为 null;:host 和 ::slotted() 是唯二合法穿透方式;自定义属性靠继承链生效,须挂载宿主元素。

attachShadow() 是起点,不是封装本身——不往 shadow root 里塞 <style></style>,就没有样式隔离。
为什么 innerHTML = '<style>...</style>' 会失效
浏览器把字符串里的 <style></style> 当成普通 HTML 节点解析,它根本不会进 CSSOM,后续改 style.textContent 或插入新规则都无效。
- 必须用
document.createElement('style')创建节点,再appendChild()到shadowRoot - 或者用现代方案:
const sheet = new CSSStyleSheet(); sheet.replaceSync('...'); shadowRoot.adoptedStyleSheets = [sheet]; -
mode: 'closed'会让el.shadowRoot永远返回null,DevTools 看不到内部结构,调试时基本没法查问题
:host 和 ::slotted() 是唯二合法穿透方式
所有其他“穿透写法”(/deep/、::ng-deep、>>>)已在 Chrome 120+、Firefox 115+ 中移除,硬写等于埋兼容性雷。
-
:host只匹配宿主元素自身,比如<my-button disabled></my-button>→:host([disabled]) { opacity: 0.5; } -
:host-context(.dark)已废弃,应改用:host(.dark)+ 外部手动加 class 到组件标签上 -
::slotted(p)可设color、font-size,但margin、display这类非继承属性会被浏览器直接忽略 -
::slotted(*)不可靠,部分浏览器不支持,且违背 slot 的设计本意:布局责任该由使用者承担
CSS 自定义属性(--var)不是“穿透”,是继承
变量能“进” shadow 内部,靠的是 DOM 树上的继承链,不是跨边界通信。它只对可继承属性生效,且必须挂在宿主元素上才有效。
- ✅ 有效:
<my-button style="--primary: #3b82f6;"></my-button>或<my-button class="theme-dark"></my-button>+.theme-dark { --primary: #1e1e1e; } - ❌ 无效:
<div class="wrapper"><my-button></my-button></div>+.wrapper { --primary: red; }—— 变量没挂到<my-button></my-button>上,进不去 - 消费时务必带 fallback:
background-color: var(--primary, #007bff);,否则变量未定义会导致样式崩溃 -
@font-face完全不继承,每个 shadow tree 需单独定义或由外部提前注入到document
字体、颜色等基础样式不继承?那是你没显式写
Shadow DOM 默认不继承 font-family、color 等,因为这些虽属可继承属性,但浏览器不会自动把它们从 light DOM “推”进来——得你主动声明。
- 在
<style></style>里加::host { font-family: inherit; color: inherit; } - 别写
body { font-family: system-ui; }期望它影响 shadow 内文字——body不是宿主,这条规则压根不参与 shadow 内部样式计算 - 查不到影子树内节点?
document.querySelector('.shadow-inner-btn')默认查 light DOM,要用shadowRoot.querySelector('.shadow-inner-btn')
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











