:disabled 是标准伪类,必须带冒号,仅匹配原生禁用表单元素(如button、input等),不匹配div等自定义元素;它反映运行时禁用状态,与[disabled]属性选择器行为不同,且disabled元素默认不可聚焦,影响:focus-within等伪类生效。

disabled 伪类不存在,要用 :disabled 伪类
CSS 中没有 :disabled 伪类这种写法——准确说,:disabled 是标准伪类,但很多人误以为它是“伪类名”而写成 disabled(漏掉冒号),导致样式完全不生效。它不是属性选择器,也不是类名,必须带冒号。
:disabled 能匹配哪些元素
它只对具有原生禁用语义的表单控件生效,包括:<button>、<input>(除 type="hidden" 外)、<select>、<textarea>、<optgroup>、<option>。注意:<div> 或自定义组件加 disabled 属性不会触发 :disabled,因为它们没有内置禁用逻辑。
-
<button disabled>点不了</button>→ ✅ 匹配button:disabled -
<input type="text" disabled>→ ✅ 匹配input:disabled -
<div disabled>xxx</div>→ ❌ 不匹配div:disabled(无效) -
<input type="hidden" disabled>→ ❌type="hidden"被排除在:disabled之外
与 [disabled] 属性选择器的区别
:disabled 是伪类,反映元素当前是否处于禁用状态(含 JS 动态设置 el.disabled = true 后仍生效);而 [disabled] 是属性选择器,只匹配显式写了 disabled 属性的 HTML 元素(哪怕后来 JS 清除了该属性,只要没重设 disabled,它还“挂着”就仍会命中)。两者行为不总一致。
input:disabled {
background-color: #f0f0f0;
cursor: not-allowed;
}
/* 和下面效果不同: */
input[disabled] {
opacity: 0.6;
}- JS 执行
inp.disabled = true→ 触发:disabled,但不添加disabled属性,所以[disabled]不匹配 - HTML 写
<input disabled>→ 两者都匹配 - JS 执行
inp.removeAttribute('disabled')→[disabled]立即失效,但若之前设过disabled = true,DOM 属性可能残留(取决于浏览器),造成不一致
常见坑:disabled 元素默认不可聚焦,:focus-within 不会触发
被 :disabled 选中的元素无法获得焦点,因此像 fieldset:disabled :focus-within 或 label:disabled:focus 这类组合基本无效。如果需要视觉反馈(比如禁用时 hover 变色),只能依赖父容器状态或 JS 模拟。
立即学习“前端免费学习笔记(深入)”;
- 禁用的
<button>无法响应:hover或:focus(部分浏览器允许:hover,但不保证) -
fieldset:disabled会禁用内部所有可交互子元素,但fieldset自身仍可被选中和设置样式 - 想让禁用按钮有 hover 效果?得用
button[disabled]:hover(仅当属性存在时),且需配合pointer-events: none的反向控制(慎用)
禁用状态的样式控制看似简单,但容易混淆伪类写法、误判匹配范围、忽略 JS 动态操作带来的差异,还有 focus/hover 行为的隐性限制——这些细节不验证,光靠“写了样式”是看不出效果的。










