button:disabled更可靠,因它匹配禁用状态本身,而[disabled]仅匹配html属性,js动态设el.disabled=true时属性未必同步;且button:disabled仅对原生可禁用元素生效,如、等,不支持或自定义组件。

别用 [disabled],直接写 button:disabled —— 它更可靠、语义正确、动态状态自动同步。
为什么 [disabled] 会漏掉禁用按钮?
HTML 属性选择器 [disabled] 只匹配 DOM 中真实存在的 disabled 属性,而 JavaScript 动态设置 el.disabled = true 时,属性(attribute)未必同步更新。比如 React/Vue 组件里 disabled={true} 渲染后可能不带 disabled 属性,只靠 IDL 属性控制状态,此时 button[disabled] 完全选不到。
-
button:disabled是伪类,匹配的是“禁用状态”本身,无论属性是否存在 -
button[disabled]是属性选择器,只看 HTML attribute,和 JS 状态脱节 - 实测:Vue 3 的
<button :disabled="loading"></button>在非 SSR 场景下常不渲染disabled属性,[disabled]失效
button:disabled 的实际生效范围有哪些?
它只对原生可禁用的表单控件有效,不是所有带 disabled 属性的元素都能被选中:
- ✅ 支持:
<button></button>、<input>(除type="hidden")、<select></select>、<textarea></textarea>、<fieldset></fieldset> - ❌ 不支持:
<div disabled>、<code><span disabled></span>、自定义 Web Component(除非显式继承HTMLElement并实现disabledIDL 属性) - ⚠️ 特殊:在
<fieldset disabled></fieldset>下的所有子表单控件也会被隐式禁用,但button:disabled不会匹配它们——得用fieldset:disabled button或fieldset[disabled] button - 写死所有颜色:
color: #999、background-color: #f5f5f5,不能依赖继承 - 加
pointer-events: none阻止误触(注意:这会让键盘 Tab 跳过该按钮,符合无障碍逻辑) - 强制禁用过渡:
transition: none !important,避免状态切换时残留动画 - 避免
filter: grayscale()—— iOS 12–14 渲染异常,高对比度模式下直接变黑
移动端 iOS Safari 上 button:disabled 样式不生效怎么办?
iOS Safari(尤其 12–14)对 :disabled 的渲染有严重缺陷:可能忽略 opacity、不更新 background-color、甚至不触发 cursor: not-allowed。必须叠加显式声明:
真正难的不是写对选择器,而是确保禁用状态在 DOM、JS 属性、CSS 样式、屏幕阅读器语义四者之间完全同步;漏掉任意一环,用户就可能点到不可操作的按钮,或键盘用户卡在“看不见却能聚焦”的地方。











