因为CSS变量作用域不跨Shadow DOM边界,document.documentElement的变量无法被shadowRoot继承,必须通过:host显式中转;常见错误包括在body或父选择器设变量、未在:host声明--x: var(--x, fallback)导致内部var()回退。

为什么document.documentElement.style.setProperty('--color', 'red')在Shadow DOM里不生效
因为:root不在Shadow DOM的继承链上——宿主元素(比如<my-button>)才是起点,<html>压根不参与它的继承计算。DevTools里右键宿主元素 → “Show inherited CSS properties”,你会发现--color根本没列出来。
常见错误包括:
- 在<body>或外层<div class="theme-dark">里设变量
- 把变量写在.wrapper > my-button { --color: red; }这种父选择器里(变量没挂到宿主节点上)
- 用all: initial或all: unset重置:host,直接清空所有自定义属性
:host是唯一合法的变量注入入口
:host不是“转发器”,而是你把变量“挂”进Shadow DOM的唯一通道。它必须显式声明在宿主自身作用域,才能被内部var(--x)读到。
三种等效方式,按场景选:
- HTML行内:<my-card style="--card-bg: #f8f9fa;">
- CSS规则:my-card[theme="dark"] { --card-bg: #1e1e1e; }
- JS动态:el.style.setProperty('--card-bg', '#f0f0f0')
注意:::part()、::slotted()、:host-context(body.dark)都无效——:host-context()只认class和属性,不支持标签名;::part()不传递变量,只暴露样式钩子。
:host { --x: var(--x, #000); }这句到底在干啥
它不是多余操作,而是在宿主节点上“中转”变量:把外部传来的--x拷贝一份到宿主自身作用域,供内部子元素继承。没有这句,哪怕你在<my-button style="--x:red">里写了,内部div { color: var(--x); }也可能 fallback。
立即学习“前端免费学习笔记(深入)”;
容易踩的坑:
- 写成:host { --x: var(--x); }(没fallback)→ 外部没设时var()返回invalid
- 写成:host { --x: inherit; } → 宿主自己没值,inherit无源可溯
- 在:host里用all: initial → 所有--*变invalid,var()立刻回退fallback
iOS Safari 16.4之前有引擎级bug
哪怕你把--theme正确设在宿主上,iOS Safari 16.4及更早版本仍可能读不到。这不是写法问题,是WebKit继承链实现缺陷,2026年4月21日才修复。线上项目若需兼容旧版iOS,得用JS手动同步变量值到shadowRoot.querySelector('style')里补一层,或者降级用adoptedStyleSheets。
调试时别只看Computed面板——如果var(--x)显示invalid,先查宿主节点的“inherited properties”,再确认是否拼错名、是否被all: initial干掉,最后才怀疑浏览器兼容性。


















