button:disabled 加 filter 没变灰,因该伪类仅匹配原生可禁用表单元素且需真实 disabled 属性;自定义组件或 div 封装不生效,iOS Safari 对 disabled 元素的 filter 渲染也不稳定。

button:disabled 为什么加了 filter 却没变灰
因为 :disabled 只匹配原生可禁用的表单元素(<button></button>、<input>、<select></select>),且必须真实存在 disabled 属性——不是 disabled="false",也不是自定义属性 data-disabled="true"。如果你用的是 <div> 封装的按钮,或 Vue/React 中的组件(如 <code><mybutton></mybutton>),button:disabled 根本不会命中。
iOS Safari(尤其是 12–14 版)对 filter 在 :disabled 元素上的渲染支持不稳定:样式可能挂载成功但视觉无变化,或快速切换时闪烁。验证方法很简单:打开 DevTools,手动删掉元素上的 disabled 属性,看灰度是否同步消失——如果没变,说明压根没走这条规则。
稳妥写法是同时声明:
button:disabled {
filter: grayscale(100%) brightness(0.92);
color: #999;
background-color: #f5f5f5;
border-color: #ddd;
cursor: not-allowed;
transition: filter 0.15s ease, opacity 0.15s ease;
}cursor: not-allowed 不生效的三个常见原因
cursor: not-allowed 是纯视觉提示,不拦截任何交互;但它本身容易被覆盖或失效:
立即学习“前端免费学习笔记(深入)”;
-
pointer-events: none会彻底阻止鼠标事件到达该元素,光标自然不会触发——此时加cursor没意义 - 父级或全局 CSS 中有更高优先级的
cursor声明(比如body { cursor: default; }),会继承覆盖子元素 - 行内样式如
style="cursor: pointer"直接覆盖了 CSS 规则,需加!important或改用更具体的选择器(如button:disabled)
真正起效的前提是:元素能接收鼠标悬停事件,且没有其他 cursor 声明干扰。移动端无需关注此项,它只影响桌面端反馈。
禁用状态不能只靠 filter 或 opacity
filter: grayscale() 和 opacity 都只改外观,不改语义也不拦行为:
- 键盘仍可
Tab到该按钮,屏幕阅读器仍播报“提交”,回车键照样触发click事件 -
opacity: 0.5会让边框、图标、阴影一并变淡,破坏可读性,还可能让辅助技术误判内容可用性 - 高对比度模式(
@media (forced-colors: active))下,filter会被系统强制忽略,按钮看起来和启用态一样
所以必须三层同步:
- DOM 层:
disabled属性(表单控件)或aria-disabled="true"(非表单元素) - CSS 层:
button:disabled或自定义 class(如.btn--disabled),显式设color、background-color、cursor - 行为层:JS 中 handler 开头加
if (el.disabled) return;,或监听前检查状态
框架里动态禁用按钮的样式陷阱
React/Vue 中常写 <button :disabled="isSubmitting"></button> 或 <button disabled></button>,但样式更新可能滞后于 DOM 属性变更,尤其在异步操作后立即启停时。
更可控的做法是用 class 控制视觉:
<button
:disabled="isSubmitting"
:class="{ 'btn--disabled': isSubmitting }"
>提交</button>对应 CSS:
.btn--disabled {
color: #999;
background-color: #f5f5f5;
cursor: not-allowed;
pointer-events: none; /* 纯触摸场景可加,但会禁用焦点 */
}注意:pointer-events: none 会同时禁用 focus 和键盘导航,若需保留 Tab 导航能力,应避免使用,改用 disabled + JS 拦截。
最易被忽略的一点:禁用态必须通过 WCAG 对比度校验——小字号文字禁用时仍需 ≥ 4.5:1,不能只凭“看起来灰一点”就认为合格。


















