:enabled仅匹配原生支持disabled属性的表单控件(如input、button、select、textarea、optgroup),不识别div或自定义组件上的disabled属性;它语义明确、响应动态禁用状态,且在fieldset继承禁用等场景下比:not(:disabled)更准确可靠。

:enabled 不是“让元素可用”的开关,它只匹配**已经真正可操作的原生表单控件**——没加 disabled 属性、没被 fieldset 继承禁用、也没被 JS 错误绕过的那些元素。
哪些元素能被 :enabled 匹配?
只认浏览器原生支持 disabled 属性的控件:
-
<input>(type="hidden"除外) <button></button>-
<select></select>和<optgroup></optgroup> <textarea></textarea>
<div disabled>、<code><span disabled></span>、自定义组件上写的 disabled 属性,:enabled 完全无视。这类元素必须靠 class 控制,比如 .is-disabled。
为什么写了 :enabled 却没生效?
最常见的是把“视觉禁用”当成了“真实禁用”:
- 只加了
pointer-events: none+opacity: 0.5,但没设disabled属性 →:enabled仍为真 - JS 设置了
el.disabled = true,但没同步写入 DOM 属性(如漏掉el.setAttribute('disabled', ''))→ 部分旧 Safari 可能不识别 - 在 Vue/React 中用
:disabled="flag",但flag初始是undefined或null→disabled属性根本没渲染出来,:enabled默认命中
:enabled 和 :not(:disabled) 能互换吗?
不能。表面看都“挑没禁用的”,但行为不同:
-
:enabled是语义伪类,只作用于支持disabled的表单控件;:not(:disabled)是逻辑取反,连<p disabled></p>这种非法写法都会被选中 - 在
<fieldset disabled></fieldset>内部,子<input>没写disabled属性,但仍被:disabled匹配 →:enabled正确排除它,而:not(:disabled)会错误命中 - IE11 对
:not(:disabled)在<option></option>上支持不稳定,:enabled更稳妥
实际样式怎么写才可靠?
别只靠颜色或透明度区分状态,要叠加多个信号:
- 用
cursor: not-allowed明确阻断交互预期 - 禁用时移除
box-shadow,避免看起来还能点 - 启用状态下慎用
:enabled:hover,确保不会覆盖到禁用按钮的悬停(禁用按钮不该响应 hover) - 批量控制时,直接给
<fieldset></fieldset>加disabled,比逐个操作子元素更可靠
复杂点在于:禁用状态可能来自属性、继承、JS 动态设置,甚至框架响应式变量渲染时机。只要 disabled 属性没真实落在 DOM 上,:enabled 就不会翻脸——它不猜意图,只看事实。











