html 标签无法直接添加自定义伪类(如 :loading),因浏览器仅识别标准伪类,未定义伪类会导致整条 css 规则静默失效;工程中应使用 data- 属性(如 [data-loading])或 web components 的 :host() 实现状态样式。

HTML 标签本身不支持自定义伪类——:host、:slotted 等是 Shadow DOM 内部的伪类,而 :is()、:where() 是逻辑组合伪类,都不是“给普通 HTML 标签添加新伪类”的机制。所谓“自定义伪类”,在真实工程中只有两种可行路径:用 Web Components 封装后在 Shadow DOM 里用原生伪类,或用 CSS 自定义属性 + 属性选择器模拟状态。
为什么不能直接给 <button></button> 添加 :loading 这类伪类
浏览器解析器只识别标准伪类(如 :hover、:focus、:disabled),任何未被规范定义的伪类(如 :loading)都会导致整条 CSS 规则失效。即使你写成 button:loading { opacity: 0.6; },浏览器会直接跳过该规则,控制台无报错,但样式就是不生效。
- 伪类不是可扩展的插件系统,它由 CSS 规范硬编码在渲染引擎中
-
document.createElement('button').matches(':loading')会抛SyntaxError - PostCSS 或 Sass 的伪类混入(
@mixin loading-state)只是预处理生成属性选择器,不是真伪类
[data-loading] 是大型组件库里最稳的状态表达方式
所有主流设计系统(Material Web、Shoelace、Ionic)都放弃“造伪类”,转而用语义化 data- 属性配合属性选择器。这不是妥协,而是对浏览器能力边界的尊重。
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
- 状态变更只需
el.setAttribute('data-loading', 'true'),无需操作 class 列表,避免classList.toggle漏掉或重复 - CSS 可写成
button[data-loading="true"] { pointer-events: none; },权重与类选择器一致,不破坏现有优先级链 - 服务端渲染时可直接输出
<ds-button data-loading="true"></ds-button>,首屏即生效,不依赖 JS 初始化 - 无障碍工具能读取
data-loading并触发aria-busy="true"同步(需 JS 补充逻辑)
Web Components 中真正可用的“自定义状态伪类”只有 :host() 和 :state()
在 Shadow DOM 内部,:host() 允许你基于自定义元素的属性匹配样式,这是目前唯一接近“自定义伪类”的原生能力。注意::state() 是实验性提案(Chrome 125+ 支持),尚未进标准,生产环境禁用。
-
:host([data-loading])✅ —— 匹配<ds-button data-loading></ds-button> -
:host(:hover)✅ —— 组合使用没问题 -
:host(.loading)❌ —— 不推荐,class 是运行时动态管理的,易与外部 class 冲突 -
:host([data-loading]):hover✅ —— 多状态叠加安全,且可被el.matches(':host([data-loading])')检测
伪类误用导致的典型线上故障
某金融后台组件库曾在线上出现按钮点击无反馈,排查发现是开发者写了 button:processing { cursor: wait; }。该规则在所有浏览器中静默失效,但开发环境因 PostCSS 插件自动转成了 button[data-processing],造成本地正常、线上异常的“幽灵 bug”。
- 伪类名拼写错误(
:hober)不会报错,只会丢弃整条规则 - 伪类嵌套过深(
div:hover > span:active > i:focus)在旧版 Safari 中兼容性断裂 - 把
:not(.disabled)当作状态开关,结果当元素同时有.disabled和.loading类时逻辑反转
真正需要关注的不是“怎么造新伪类”,而是如何让 data- 属性的生命周期与组件状态严格对齐——比如 attributeChangedCallback 中同步更新 aria-busy,以及在 disconnectedCallback 中清理定时器,否则状态残留比伪类缺失更难 debug。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










