::part 只能选中显式标记 part 属性的 Shadow DOM 内部节点,大小写敏感、不作用于 slot 投射内容、不支持嵌套或组合写法,是组件作者主动暴露的样式契约接口。

::part 只能选中显式标记 part 属性的节点
因为 ::part 不是穿透 Shadow DOM 的“万能选择器”,它只对组件作者在 Shadow DOM 内部**手动添加了 part="xxx" 属性的元素**生效。没加这个属性,哪怕结构再近、层级再浅,外部 CSS 也完全无法匹配。
- 常见错误:写
my-button::part(icon),但组件内部的<svg>根本没设part="icon" - 大小写敏感:
part="Icon"和::part(icon)不匹配 - 不能靠结构推断:即使按钮里唯一一个
<span>是图标容器,不加part就不算“暴露”
::part 不作用于 slot 投射内容或未进入 shadow tree 的节点
::part 的作用域严格限定在当前自定义元素的 Shadow DOM **内部节点**,和插槽(<slot>)无关。投射进来的 light DOM 内容属于父级上下文,不属于该 shadow tree,因此永远无法被 ::part 选中。
- 例如:
<my-button><span slot="icon">⚙️</span></my-button>中的<span>是插槽内容,不是 shadow 内部节点 - 想样式化它,得用
::slotted([slot="icon"]),而不是::part(icon) - 嵌套自定义元素内部的子元素,除非它自己也暴露
part,否则上层组件无法跨 shadow boundary 使用::part触达
::part 不支持链式、嵌套或伪元素组合写法
::part 是一个原子级伪元素,语法上不允许与其他选择器拼接。浏览器会直接忽略非法组合,不会报错,但也不会生效。
- 错误写法:
my-button::part(icon)::before、my-button::part(icon) > span、my-button::part(icon):hover - 正确做法:伪元素或状态样式必须在组件内部的 shadow style 中定义,比如在
<template>里写button[part="icon"]::before { ... } - 也不能写
::part(icon)::part(label)——::part不支持嵌套,它只匹配单个带part属性的元素
替代方案取决于你控制组件源码与否
如果你是组件使用者,只能依赖作者是否暴露了足够的 part;如果你是组件作者,就得主动设计哪些内部节点需要被定制,并加上 part 属性。
立即学习“前端免费学习笔记(深入)”;
- 使用者无权读取、JS 查询或监听
part节点 —— 它纯属样式契约,仅限 CSS 声明 - 不想暴露太多内部结构?可用语义化
part名,如part="control"而非part="inner-button" - 需要更灵活穿透?现代框架中可考虑
:deep()(Vue)或/deep/(已弃用,仅旧版支持),但它们不适用于原生 Shadow DOM
::part 的存在本身就意味着一种协作契约——它不是浏览器给开发者的“后门”,而是组件作者主动划出的样式接口。没暴露,就等于没开放;暴露错了名,就等于关上了门。


















