adoptedStyleSheets 仅对 ShadowRoot 实例有效,document 上操作被静默忽略;需先 attachShadow 再赋值;动态更新用 replaceSync() 或 insertRule();移除需过滤数组或清空规则;兼容性需检测并降级。

adoptedStyleSheets 只能在 Shadow DOM 中生效
直接在 document.adoptedStyleSheets 上操作是无效的——这个属性只对 ShadowRoot 实例有意义。浏览器会静默忽略对 document 的赋值,且不报错。常见错误是误以为它能替代 <link> 或 <style> 全局注入。
正确做法是:先创建带 mode: "open"(或 "closed")的 shadow root,再对其 adoptedStyleSheets 赋值:
const shadow = el.attachShadow({ mode: "open" });
const sheet = new CSSStyleSheet();
sheet.replaceSync(`.box { color: red; }`);
shadow.adoptedStyleSheets = [sheet];
动态添加样式表必须用 replaceSync() 或 insertRule()
CSSStyleSheet 实例不能直接修改 cssText,也不支持 innerHTML。试图写 sheet.cssText = "..." 会静默失败;而 sheet.replace("...") 是异步的,若立即触发渲染可能样式未就绪。
- 高频更新推荐
replaceSync()(同步,无 Promise) - 增量追加规则用
insertRule(".item:hover { opacity: 0.8; }", sheet.cssRules.length) - 移除某条规则需先查索引,再用
deleteRule(index)—— 没有按选择器删除的快捷方式
移除样式表只能靠重新赋值 adoptedStyleSheets 数组
没有 shadow.unadoptStyleSheet() 这样的方法。要“移除”某个样式表,必须重建 adoptedStyleSheets 数组,过滤掉目标 CSSStyleSheet 实例:
立即学习“前端免费学习笔记(深入)”;
const targetSheet = sheets[0]; shadow.adoptedStyleSheets = shadow.adoptedStyleSheets.filter(s => s !== targetSheet);
注意:必须用引用比对(===),不能用 JSON.stringify 或内容比对 —— 多个 CSSStyleSheet 内容相同也互不相等。
如果只是临时禁用,更轻量的做法是清空其规则:sheet.replaceSync(""),避免数组重分配和 DOM 重排开销。
兼容性与 fallback 必须手动处理
adoptedStyleSheets 在 Safari 17.4+ 才默认开启,旧版 Safari 需启用实验性功能;Firefox 直到 115 才支持,且要求 dom.webcomponents.enabled 为 true。Chrome 和 Edge 支持较好(94+)。
无法降级到 <style> 插入,因为全局样式会污染其他组件。稳妥方案是:检测支持后才启用 shadow + adoptedStyleSheets,否则回退到 scoped-style 模拟(如属性选择器前缀 + style 标签注入):
if (CSSStyleSheet.prototype.replaceSync && 'adoptedStyleSheets' in ShadowRoot.prototype) {
// 使用 adoptedStyleSheets
} else {
// 回退:动态创建 <style> 并 append 到 shadow root
}
真正麻烦的是 SSR 场景:服务端没有 CSSStyleSheet 构造函数,所有相关逻辑必须包裹在 if (typeof window !== "undefined") 中,且首次 hydrate 时需重新建立样式引用关系。



















