::part()是组件作者主动暴露的样式接口,仅匹配shadow DOM内显式声明part="label"的静态字符串属性节点,大小写敏感、不支持动态绑定或slot内容,Firefox至今未实现,须用CSS变量降级。

::part() 不是穿透工具,而是组件作者主动暴露的“样式接口”——没加 part 属性的节点,外部 CSS 根本看不见,也不会报错。
为什么 ::part(label) 写对了却完全没反应
最常见原因是目标元素根本没声明 part="label"。它不匹配 class、不匹配 slot 名、不匹配语义猜测名,只认字面量字符串属性,且大小写严格敏感。
- 检查方式:在 DevTools 中右键组件 → “Inspect”,进入
#shadow-root,手动搜索part="label" -
part="Label"和::part(label)不匹配;part="label required"可被::part(required)单独选中 - 宿主元素(如
<my-input>)自身不能加part,::part()只作用于 shadow 内部子节点
::part() 的合法写法和硬性限制
::part() 是单点锚定,不是选择器起点。它后面不能接任何其他选择器,也不能嵌套使用。
- ❌ 非法:
my-input::part(wrapper) input、my-input::part(label)::before、:host::part(label) - ✅ 合法:
my-input::part(label)—— 所有样式必须直接定义在这个伪元素上 - 不支持伪元素(
::before)、属性选择器([disabled])、关系选择器(>、+)跟在后面 - 动态绑定无效:
part={this.state.type}或:attr(part)都不生效;part必须是静态字符串
浏览器兼容性与降级必须做
Chrome/Edge 97+ 原生支持,但 Safari 自 15.4 起需手动开启实验功能,Firefox 截至 2026 年 9 月仍未实现 —— @supports selector(::part(foo)) 在 Firefox 中永远返回 false。
立即学习“前端免费学习笔记(深入)”;
- 真机测试底线:iOS 16.7 + Safari、macOS 12.6 + Safari;别信 CanIUse 的“支持”标记就上线
- 关键样式必须用
@supports包裹,并 fallback 到 CSS 自定义属性,例如:--my-input-label-color - 组件内部必须消费该变量:
color: var(--my-input-label-color);,否则降级失效 - 禁用态背景、必填标红等核心视觉逻辑,不能只靠
::part()控制,否则 Safari 用户看到的是默认样式
嵌套 Shadow DOM 中 exportparts 是刚需
如果组件结构含子自定义元素(如 <editor-toolbar>),且你想从最外层定制它的内部部件,仅父组件写 part="toolbar" 不够——必须用 exportparts 显式透传。
- 父组件需声明:
<editor-toolbar exportparts="button bold-btn italic-btn"></editor-toolbar> - 外部才能写:
my-editor::part(bold-btn) { color: blue; } -
exportparts是显式白名单,未列出的内部part无法从最外层访问
真正难的不是写对 ::part(),而是确认组件是否暴露了你要的 part、是否在正确层级透传、是否在所有目标浏览器里有可用 fallback —— 这些环节漏掉任何一个,样式就静默失效。


















