Shadow DOM 布局规则须内置于 shadowRoot 样式表中,通过动态创建 style 节点挂载;:host 专控宿主自身布局,内部元素样式作用域隔离,slot 投影内容布局受限于 ::slotted(*) 继承性属性。

Shadow DOM 的私有布局规则必须定义在 Shadow 树内部的样式表中,不能依赖外部 CSS 文件或全局 style 标签。布局控制权完全归属 shadowRoot 内部,外部样式无法穿透影响子元素的位置、尺寸或盒模型 —— 这不是靠优先级压制,而是浏览器在解析阶段就跳过跨 boundary 的匹配。
布局规则必须写进 shadowRoot 的
不能把 <style> 直接拼进 shadowRoot.innerHTML 字符串里,那样会被当普通 HTML 解析,不进入 CSSOM,后续也无法动态修改规则。正确做法是:
- 用
document.createElement('style')创建样式节点 - 通过
textContent设置 CSS 规则(避免 innerHTML 解析风险) - 调用
shadowRoot.appendChild(style)挂载到影子根上
:host 是唯一能设置宿主自身布局的入口
宿主元素(比如 <my-card>)本身的 display、position、margin、width 等布局属性,只能通过 :host 在 shadow 内部样式中定义:
-
:host { display: block; width: 300px; margin: 16px; }—— 控制组件容器行为 -
:host([size="large"]) { width: 500px; }—— 响应宿主属性变化 -
:host(.compact) { padding: 8px; }—— 响应宿主 class
注意::host 只作用于宿主标签自身,不涉及 slot 投影内容,也不支持后代选择器如 :host .content 来控制内部结构。
内部元素布局要靠 shadow 内部选择器直接写
Shadow DOM 内部的 div、section、button 等元素,布局规则和普通 HTML 一样写,但作用域仅限于该 shadowRoot:
.modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; }#header { padding: 24px; background: #f8f9fa; }button.primary { flex: none; min-width: 120px; }
这些规则不会泄露出去,也不会被外部样式覆盖 —— 浏览器根本不会把全局 CSS 规则纳入这个 shadow tree 的样式计算流程。
slot 投影内容的布局需谨慎处理
通过 <slot> 投入的内容属于 light DOM,它本身不受 shadow 内部布局规则约束。如果想统一控制投影内容的外边距或行高:
- 可用
::slotted(*)设置继承性属性(如color、font-size、line-height) - 但禁止用
::slotted(*)设置margin、display、width等布局属性 —— 规范明确限制,浏览器会忽略 - 若需强干预布局,应在宿主元素上预留 class 或属性,再配合
:host(.with-header) > .content类选择器间接影响结构


















