::slotted()仅匹配slot分发的直接子节点,不穿透Shadow DOM,不作用于slot自身或fallback;需显式分发且初始即确定,动态添加内容不触发重匹配。

::slotted() 只能选择 slot 中的直接子节点
它不穿透 Shadow DOM 边界,也不能匹配 slot 内部嵌套的后代元素。比如 Hello world,::slotted(p) 能命中 ,但 ::slotted(em) 无效——因为 并不在 slot 的“顶层”。
- 只对被
实际分发(distributed)的节点生效,不是所有 light DOM 子节点都自动可选 - 若使用
,必须用::slotted([name="xxx"])或对应选择器,不能靠结构推断 - Chrome 96+ 支持
::slotted(*:not(.hidden))这类带伪类的写法,但 Safari 16.4 前不支持,慎用复杂条件
::slotted() 无法设置 slot 自身或 fallback 内容样式
很多人误以为给 标签加 class 就能用 ::slotted(.my-class) 匹配到它自己——不行。::slotted() 的目标永远是“被插入 slot 的那些外部节点”,不是 slot 元素本身,也不是 slot 的 fallback(即 中的文字)。
- 想控制 fallback 文字样式?只能在 slot 外层包一层
,再用普通 CSS 选中 -
上的 class 对::slotted()完全无意义 - 如果 slot 没有接收到任何内容,
::slotted(*)不会匹配任何东西,也不会触发 fallback 渲染逻辑
与 :host、:host-context 的作用域边界必须分清
::slotted() 是唯一能从 shadow root 内部“反向影响” light DOM 节点样式的伪元素,但它和 :host 完全不同:后者作用于自定义元素自身,前者只作用于它的子内容。三者共存时容易混淆优先级和层级。
-
:host ::slotted(p)和::slotted(p)效果一样,因为::slotted()必须写在 shadow root 内,天然受:host作用域约束 -
:host-context(.dark) ::slotted(p)有效,但前提是 light DOM 中该自定义元素的**祖先**有.dark类——不是 slot 内容的祖先 - 若同时写了
::slotted(p) { color: red; }和 light DOM 中的p { color: blue; },后者会胜出(light DOM 样式优先级更高),这是常被忽略的覆盖失效原因
动态 slot 分发后 ::slotted() 不会重计算样式
当 JS 修改了 slot 内容(比如用 appendChild() 动态加节点),浏览器不会重新触发 ::slotted() 的匹配逻辑——它只在初始分发时确定一次哪些节点被分发到了哪个 slot。
- 新增节点若没被显式 assign 到某个
,即使结构上“看起来”在 slot 里,也不会被::slotted()选中 - 用
slot.setAttribute('name', 'xxx')切换 slot 分发目标,不会导致已渲染的样式刷新;需手动强制重绘(如 toggle class)或依赖属性变更触发更新 - 服务端渲染(SSR)或 hydrate 场景下,若初始没有分发内容,
::slotted()规则实际不会应用,JS 补内容后样式可能错位
事情说清了就结束。真正在意样式穿透的人,往往卡在“为什么我改了内容,样式却没变”——答案通常不在 CSS 写法,而在 slot 分发是否真的发生了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











