part属性不是CSS变量,需在自定义元素中通过exportparts显式导出才能被:part()选中;未导出时:part()无效,且无法穿透Shadow DOM边界,动态变更part属性也不会触发样式重计算。

part属性不是CSS变量,它需要显式声明才能被:part()选中
很多人以为给元素加part="header"就能直接用:part(header)改样式,结果发现完全不生效。根本原因是:浏览器不会自动把任意part值暴露为可样式化接口——必须先在自定义元素内部通过exportparts或part属性显式导出。
常见错误现象:
- 子应用写了
<my-card part="title"></my-card>,主应用写my-card:part(title) { color: blue },但标题颜色没变 - 用了
exportparts="title:header-title",却在 CSS 里写:part(title)而不是:part(header-title)
正确做法:
- 在自定义元素定义时,用
exportparts="title:header-title btn:primary-btn"明确映射内部结构 - 若组件内部是 Shadow DOM,且未使用
exportparts,则外部:part()完全无效 -
part属性本身不触发样式重计算,只作为标识;真正起效靠的是:part()选择器配合构建时/运行时注入的 CSS 规则
微前端里:part()无法穿透Shadow DOM边界,除非主应用也用closed shadow
qiankun 或 MicroApp 启用strictStyleIsolation: true后,子应用容器会被包裹一层 light DOM 节点(如<div data-qiankun="app-a">),但子应用内部若用了attachShadow({ mode: 'open' }),:part()就只能作用于该 shadow 的 host 元素,不能深入内部节点。
立即学习“前端免费学习笔记(深入)”;
也就是说:my-app:part(title)只能匹配<my-app part="title">这个 host,不能匹配它 shadow 内部的<h2 part="title">——后者需在 shadow 内部单独写 CSS,或由子应用自己导出。
真正能跨层级控制的路径只有两条:
- 子应用在
shadowRoot内定义:part()规则,并通过adoptedStyleSheets注入,主应用无需额外操作 - 主应用也用
attachShadow({ mode: 'closed' })包裹整个微前端容器,再用:host > my-app:part(title)定位,但代价是失去对子应用 light DOM 的直接 JS 访问能力
part + :part()在主题包中容易漏掉第三方库组件的part声明
Ant Design、Element Plus 这类 UI 库默认不设part属性,它们的.ant-btn、.el-button仍走全局 class 路线。你给<el-button part="primary">加part,但库源码没做exportparts,:part(primary)照样无效。
实操建议:
- 不要依赖第三方组件自动支持
part,要么 fork 修改源码加exportparts,要么封装一层 wrapper 组件手动透传part并导出 - 主题包中所有
:part()规则必须配套检查子应用是否实际渲染了对应part值——可用document.querySelectorAll('[part]')快速验证 - 构建时用 PostCSS 插件(如
postcss-part-selector)将:part(theme-dark)重写为[data-theme="dark"] :part(theme-dark),避免被主应用样式覆盖
主题切换时part属性变更不会触发:part()重匹配,得靠CSS自定义属性兜底
part是静态 HTML 属性,设置后不会随状态变化自动更新。比如你用 JS 切换主题:el.setAttribute('part', 'theme-dark'),已挂载的:part(theme-dark)规则不会重新应用——浏览器不监听part变更,也不触发样式重计算。
更可靠的做法是组合使用:
- 用
document.documentElement.setAttribute('data-theme', 'dark')驱动全局 CSS 自定义属性 - 子应用内用
getComputedStyle(document.documentElement).getPropertyValue('--theme-color')读取,并绑定到组件状态 -
:part()只用于固定结构的主题区域(如 header、sidebar),动态部分交给--theme-*变量控制
真正难搞的从来不是怎么写:part(),而是怎么让 theme 包里的每个part都真实存在、被导出、不被第三方覆盖、还能响应 runtime 变更——漏掉任意一环,主题就断层。



















