禁用状态应通过 filter: saturate() brightness() 调整饱和度与明度来实现,避免 opacity 导致可访问性与渲染问题;需为 checkbox/radio 单独处理,深色模式下反向微调,并确保 WCAG 合规与跨浏览器兼容。

disabled状态下的颜色变灰不是靠opacity
直接给 :disabled 元素加 opacity: 0.6 看似简单,实际会连文字、边框、背景图一起模糊,还可能让屏幕阅读器误判可访问性层级。真正干净的做法是只调低色彩饱和度和明度,保留清晰边缘和语义结构。
- 用
filter: saturate(0.3) brightness(0.85)替代opacity,对大多数输入框(input、select、textarea)更可控 -
filter在 Safari 15.4+ 和 Chrome 100+ 支持良好,但旧版 Edge(≤18)不支持,需配合color: #999+background-color: #f5f5f5回退 - 别在
:disabled上改cursor:有些系统(如 macOS)会自动覆盖为not-allowed,手动设cursor: default反而干扰可访问性
input[type="checkbox"] 和 radio 的 :disabled 处理要单独写
原生复选框和单选按钮的禁用态无法靠 filter 统一控制——它们的外观由系统渲染,filter 对其内部伪元素(如 ::before)无效。必须用属性选择器显式干预。
- 写成
input[type="checkbox"]:disabled + label或input[type="radio"]:disabled + label,给关联的label降饱和度,而非 input 本身 - 如果用了自定义 checkbox(比如用
span模拟),禁用逻辑得同步控制tabindex="-1"和aria-disabled="true",否则键盘用户仍能聚焦 - 别依赖
:disabled::after:伪元素在禁用表单控件上多数浏览器不渲染
避免在 :disabled 中重置 border-color 导致视觉断裂
很多 CSS 重置库(如 Normalize.css)默认给 input:disabled 设了 border-color: #ccc,和你主色系的禁用态不一致,容易显得突兀。
- 显式覆盖:比如主色是
#4a6fa5,禁用时建议用border-color: hsl(210, 20%, 70%),保持色相一致,只降低饱和与明度 - 别用
border: none或border: 1px solid transparent:会破坏输入框高度一致性,尤其在 flex 布局中引发基线错位 - 如果用了 box-shadow 模拟 focus 状态,记得在
:disabled中也清掉:box-shadow: none,否则禁用后还留着焦点阴影就奇怪了
dark mode 下 :disabled 的饱和度调整要反向
深色主题里,降低饱和度会让禁用元素发“脏”,看起来像失效而不是禁用。这时候不是继续降饱和,而是适当提亮+微调色相。
立即学习“前端免费学习笔记(深入)”;
- 深色模式下推荐:
filter: saturate(0.7) brightness(1.15),比浅色模式更保守 - 用
@media (prefers-color-scheme: dark)包裹时,确保它在浅色样式之后,否则会被覆盖 - 别用
color: #666这类固定灰度值:在深色背景下对比度太低,WCAG AA 都难达标;改用color: hsl(0, 0%, 60%)并随主题动态算值更稳妥
禁用态的视觉反馈本质是「降低信息权重」,不是「隐藏」。饱和度和明度的组合调节比单纯变灰或变透明更能守住这个边界——尤其当用户开了系统级高对比度模式时,filter 依然生效,而 opacity 往往被强制重置。


















