Shadow DOM 是唯一真正隔离样式的机制,因 scoped 和 BEM 无法阻止强制覆盖;需在构造函数或 connectedCallback 中用 {mode: 'open'} 创建,样式须通过 DOM 方法注入,且仅 :host 和 ::slotted() 可跨边界透传。
<style scoped> 或 BEM 类名无法真正隔离样式因为 scoped 属性已在 Chrome 120+ 和 Firefox 115+ 中被移除,它从未真正进入 CSSOM;BEM 类名只是命名约定,button { color: red !important } 依然能覆盖你写的 .my-btn__text。Shadow DOM 是唯一由浏览器在解析阶段就裁剪样式作用域的机制——外部规则压根不进 shadowRoot 的 CSSOM,不是权重不够,是根本“看不见”。
attachShadow() 必须在构造函数或 connectedCallback 中调用延迟到 click 或 setTimeout 里调用会失败,且一个元素只能 attach 一次,重复调用抛出 Failed to execute 'attachShadow' on 'Element': Shadow root cannot be created on a node already hosting a shadow root. 错误。
{ mode: 'open' },'closed' 会让 element.shadowRoot 永远返回 null,调试时无法 inspect 内部结构disconnectedCallback 或事件处理器中调用CSSStyleSheet 实例 + adoptedStyleSheets,但注意 Safari 16.4+ / Chrome 73+ 才稳定支持innerHTML
写 shadowRoot.innerHTML = `<div></div><style>.box { width: 100px; }</style>` 看似简洁,但 <style> 被当普通 HTML 解析,不进 CSSOM,后续 JS 修改 style.textContent 完全无效,甚至触发 FOUC。
document.createElement('style') + textContent + appendChild()
<style> 里写 :host { font-family: inherit; color: inherit; },否则 <body> 设置的字体不会透传::slotted(p) 只影响 slot 中的直接子 <p>,且仅支持可继承属性(color、font-family、background-color),不能设 margin 或 display
:host 和 ::slotted() 是仅有的合法跨边界通道W3C 规范只保留这两个伪类作为边界协议接口,其余方式(如 /deep/、::ng-deep)已在 Chrome 120+ 和 Firefox 115+ 中移除。它们不是选择器增强,而是封装契约——用错等于主动放弃隔离。
立即学习“前端免费学习笔记(深入)”;
:host([disabled]) 有效,:host-context(.theme-dark) 才能响应外部 <body class="theme-dark">
:host div.title —— :host 只匹配宿主元素自身(如 <my-card>),不匹配其内部节点::slotted(*) —— 行为不一致,且违背 slot 的设计本意:内容布局责任应由使用者承担