按钮必须用 disabled 而非 readonly,因后者不被支持;disabled 禁用交互且阻止表单提交,值不参与序列化,需配合 aria-disabled 保障可访问性。

disabled 能用在按钮上,readonly 根本不生效
按钮(<button>、<input type="button">、<input type="submit">)**不支持 readonly 属性**。给按钮加 readonly="true" 完全没效果,点击照常触发,样式也不变,浏览器直接忽略该属性。
必须用 disabled 控制按钮的禁用状态。Bootstrap 会自动为 disabled 按钮添加灰阶背景、低透明度和 cursor: not-allowed 样式,同时阻止所有交互(点击、focus、键盘操作)。
-
disabled是布尔属性:设为true即禁用,设为false或移除属性即启用 - JS 动态控制推荐写法:
btn.disabled = true(不是btn.setAttribute('disabled', 'true')) - 禁用后按钮的
value仍可读写,但不会参与表单提交——这点对<input type="submit">尤其关键
表单提交时,disabled 按钮的值压根不会发送
如果按钮是 <input type="submit" name="action" value="save">,加了 disabled 后,整个字段(包括 name 和 value)会被浏览器从序列化结果中剔除。FormData、URL 查询参数、原生 form.submit() 都不包含它。
这跟 readonly 无关——因为按钮根本不认 readonly。但有人误以为“只读=值还在”,试图给按钮加 readonly 来保留提交标识,结果既没禁用成功,也没达到预期语义。
- 需要按钮禁用且不参与提交 → 用
disabled - 需要按钮禁用但又想让后端知道“用户点了哪个按钮” → 不可行,得换方案(比如用隐藏域 + JS 提交前补值)
- 提交前临时禁用按钮防重复点击 → 必须用
disabled,且建议配合 loading 状态视觉反馈
为什么不能对按钮用 readonly 模拟“只读”行为
readonly 的设计目标从来就不是按钮。它的语义是“内容可展示、可聚焦、可复制,但不可编辑”,而按钮没有“内容编辑”的概念。W3C 规范明确将 readonly 限制在 <input>(仅 text/password/search/tel/url/email/number)和 <textarea> 上。
强行在按钮上写 readonly,不仅无效,还会造成维护困惑:别人读代码时会误判意图,也可能被 Linter 报警(如 ESLint 的 jsx-a11y/no-unsupported-elements)。
- 想让按钮“看起来像不能点但还能获取焦点” → 不推荐。这违反可访问性原则,屏幕阅读器无法正确传达控件状态
- 真有特殊交互需求(如 tooltip 触发)→ 用 CSS +
pointer-events: none+aria-disabled="true"组合,但必须手动处理键盘焦点逻辑 - 别为了“视觉上不灰”而牺牲语义和兼容性
Bootstrap 中按钮 disabled 的样式和可访问性要点
Bootstrap 的 .btn:disabled 样式依赖原生 disabled 属性,不是靠 class 模拟。如果你只加 class="disabled" 而不加 disabled 属性,样式可能相似,但语义丢失:屏幕阅读器读不出“已禁用”,form.elements 仍会包含该按钮,JS focus() 可能意外成功。
正确做法始终是操作原生属性。Bootstrap 4+ 还要求配合 aria-disabled="true"(虽然非必需,但增强兼容性),尤其当按钮是自定义组件或通过 JS 渲染时。
- 禁用按钮必须同时具备:
disabled属性 +aria-disabled="true" - 启用时,要同时移除
disabled属性和aria-disabled属性(不要只设aria-disabled="false") - 避免全局重写
button:disabled样式时破坏透明度或 pointer-events,否则可能影响移动端点击穿透
value,只要 disabled 在,后端就收不到这个字段——这不是 Bug,是浏览器规范行为。


















