Shadow DOM 主题依赖 CSS 变量挂载于宿主元素+显式 fallback+逐处消费:变量须设在宿主(非 body/wrapper),var() 必带 fallback,运行时用 setProperty() 动态更新。

Shadow DOM 本身不提供主题功能,它只提供样式边界;真正实现主题配置,靠的是 CSS 变量(Custom Properties)+ 宿主元素显式挂载 + 每处消费都带 fallback —— 缺一不可。
变量必须挂在宿主元素上,不能写在 body 或 wrapper 里
Shadow DOM 截断选择器匹配,但继承链仍向上穿透。变量只有定义在宿主标签自身,内部才能读取到。
- ✅ 正确:
<my-button style="--button-bg: #52c418;"></my-button>或<my-card class="dark"></my-card>配合.dark { --card-bg: #1d1d1d; } - ❌ 错误:
body { --primary-color: #1890ff; }或.app-wrapper { --primary-color: #1890ff; }—— 这些不在宿主上,shadow 内完全不可见 - ⚠️ 小程序注意:不支持
:root,必须用page { --theme-color: #1a73e8; }
所有 var() 必须带 fallback,否则静默失效
没设变量时,var(--x) 计算结果为 invalid,浏览器可能回退到继承值或初始值(比如深色背景上文字变黑不可见)。
- ✅ 正确写法:
color: var(--text-color, #333);、border-radius: var(--radius, 4px);、box-shadow: var(--elevation, 0 2px 8px rgba(0,0,0,.15)); - ❌ 危险写法:
color: var(--text-color);—— 无 fallback,主题未初始化时极易崩溃 - ⚠️ fallback 不支持嵌套:
var(--color, var(--fallback))无效
在 shadow 内安全消费变量的写法
不能指望“挂一次就全生效”,每个需响应主题的位置都要手动写 var(),包括伪元素、内联 SVG、slot 内容等。
- 推荐在
:host中定义中间变量::host { --btn-bg: var(--theme-primary, #3b82f6); --btn-text: var(--theme-bg, #fff); },内部再引用这些中间变量,便于统一维护 - svg 图标要单独设 fill:
svg { fill: var(--btn-bg); },否则换主题时图标颜色不会变 - ::slotted() 只支持可继承属性:
::slotted(p) { color: var(--text-color); }有效;::slotted(*) { margin: 16px; }无效(margin 不可继承)
运行时切换主题,优先用 setProperty()
靠切换 class 再配 CSS 规则耦合重、调试难;直接操作宿主 style 更精准、可控。
- ✅ 实例:
buttonEl.style.setProperty('--button-bg', '#13c2c2'); - ✅ 全局主题更新:
document.documentElement.style.setProperty('--theme-accent', '#faad14'); - ⚠️ 小程序动态绑定 style 要拼完整字符串:
style="{{ 'color: ' + textColor + '; --icon-size: ' + iconSize + 'px;' }}",漏分号或单位会静默失败


















