:defined伪类是自定义元素样式就绪的唯一可靠信号,仅在元素完成注册、解析与升级后匹配成功,用于避免FOUC和样式错乱;须配合:not(:defined)做占位控制,不可用class/id替代,且无polyfill回退。

:defined 伪类是自定义元素样式就绪的唯一可靠信号
浏览器对 customElements.define() 的执行是异步的,而 CSS 解析和渲染是同步进行的。如果不加控制,自定义元素在定义完成前就可能被渲染,导致样式错乱或 FOUC(无样式内容闪烁)。:defined 就是为此而生——它只在元素被成功注册并升级为 custom element 后才匹配成功。
常见错误现象:页面刚加载时,<my-button> 显示为未样式化的空白块,几毫秒后才“闪”出正确样式;或 JS 尚未注册组件时,CSS 已经尝试应用 .my-button 类,结果无效。
- 必须配合
:not(:defined)做降级占位:比如my-loading-card:not(:defined) { display: flex; align-items: center; }给骨架占位提供基础布局 - 不能用
class或id替代:它们无法反映元素是否真正“可用”,仅靠类名触发样式会提前生效 - 不支持 polyfill 回退:旧版 Safari(:defined,需配合 feature detection + JS fallback
伪类组合策略决定组件状态粒度是否可控
大型组件库中,单个组件常需表达「禁用」「加载中」「验证失败」「只读」等多种叠加态。纯靠 class 切换易爆炸(btn--disabled--loading--error),而伪类组合能自然分层。
使用场景:表单控件需要同时响应用户交互(:hover)、焦点(:focus)、有效性(:invalid)和自定义状态(:state(error) 不合法,但可借 [data-state="error"] + 伪类逻辑模拟)。
立即学习“前端免费学习笔记(深入)”;
-
:disabled和:read-only语义不同::disabled阻断所有交互且不参与表单提交,:read-only允许聚焦和选择文本,二者样式应区分 -
:focus-within比 JS 监听更轻量:用于下拉菜单、复合输入框等需“子元素获焦即激活父容器”的场景 - 避免嵌套伪类滥用:如
input:focus:invalid可行,但input:focus:invalid:hover在实际交互中几乎不会触发(悬停时通常已失焦)
伪类优先级与 BEM 命名冲突的实际调和方式
伪类权重(0,1,0)和类选择器一致,但 BEM 中像 .btn__icon--large 这种高 specificity 的写法,容易压过 button:disabled .btn__icon,导致禁用态图标样式失效。
性能影响:过度依赖高权重选择器会拖慢 CSSOM 构建,尤其在含数百个组件的 SPA 中,重排重绘开销明显。
- 禁用态样式必须用
:disabled直接修饰根元素,而非靠 class:写button:disabled { opacity: 0.5; },别写.button--disabled - BEM modifier(
--)只用于外观变体(颜色、尺寸),不用于状态:把.button--disabled改为button:disabled,让语义回归 DOM 状态本身 - 必要时用
!important是合理选择:比如第三方 UI 库强制设了.select:disabled,你又必须覆盖,此时加!important比改整个选择器链更可控
自定义伪类不存在,但 data-* + 属性选择器是最接近的替代方案
CSS 标准里没有 :loading、:error、:success 这类自定义伪类,强行用 JS 动态加 class(如 is-loading)会导致 class 名泛滥、命名冲突、难以维护。
更干净的做法是统一用 data- 属性驱动样式,它天然支持属性选择器,且语义明确、无全局污染风险。
- 统一前缀防冲突:所有状态属性用
data-ui-state或项目专属前缀如data-shop-state - 用属性值做状态标识:
button[data-ui-state="loading"]、input[data-ui-state="error"],比.is-loading更具可读性 - JS 控制只需一行:
el.setAttribute('data-ui-state', 'loading'),无需 classList 切换、去重、容错
真正难处理的是跨组件状态联动(比如一个按钮的 loading 状态要同步影响旁边提示文字),这已经超出 CSS 能力边界,得靠状态管理机制兜底——伪类和属性选择器只是把“状态到样式的映射”这件事做得更稳、更轻、更可预测。



















