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

::slotted() 只能选择 slot 中的直接子节点
它不穿透 Shadow DOM 边界,也不能匹配 slot 内部嵌套的后代元素。比如 <my-card><p>Hello <em>world</em></p></my-card>,::slotted(p) 能命中 <p></p>,但 ::slotted(em) 无效——因为 <em></em> 并不在 slot 的“顶层”。
- 只对被
<slot></slot>实际分发(distributed)的节点生效,不是所有 light DOM 子节点都自动可选 - 若使用
<slot name="xxx"></slot>,必须用::slotted([name="xxx"])或对应选择器,不能靠结构推断 - Chrome 96+ 支持
::slotted(*:not(.hidden))这类带伪类的写法,但 Safari 16.4 前不支持,慎用复杂条件
::slotted() 无法设置 slot 自身或 fallback 内容样式
很多人误以为给 <slot></slot> 标签加 class 就能用 ::slotted(.my-class) 匹配到它自己——不行。::slotted() 的目标永远是“被插入 slot 的那些外部节点”,不是 slot 元素本身,也不是 slot 的 fallback(即 <slot>fallback text</slot> 中的文字)。
- 想控制 fallback 文字样式?只能在 slot 外层包一层
<span></span>,再用普通 CSS 选中 -
<slot class="s1"></slot>上的 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></slot>,即使结构上“看起来”在 slot 里,也不会被::slotted()选中 - 用
slot.setAttribute('name', 'xxx')切换 slot 分发目标,不会导致已渲染的样式刷新;需手动强制重绘(如 toggle class)或依赖属性变更触发更新 - 服务端渲染(SSR)或 hydrate 场景下,若初始没有分发内容,
::slotted()规则实际不会应用,JS 补内容后样式可能错位










