单选按钮组整体禁用应使用 disabled 属性而非 readonly,因 radio 不支持 readonly;需作用于每个 input 或用 fieldset 包裹并设 disabled 才生效,且 disabled 元素值不提交。

单选按钮组整体禁用用 disabled,不是 readonly
HTML 中 <input type="radio"> 不支持 readonly 属性——设了也无效,浏览器直接忽略。真正起作用的只有 disabled。一旦给任意一个单选按钮加了 disabled,它就无法聚焦、无法点击、不会触发表单提交值;但要注意:disabled 元素的值**不会随表单一起提交**。
常见错误是给整个 <fieldset></fieldset> 或父容器加 disabled ——没用,必须作用在每个 <input> 上。稳妥做法是统一控制:
- 用 JavaScript 批量设置所有同名
name的 radio 的disabled = true - 或服务端渲染时,为每个 radio 标签显式写入
disabled - 若用 CSS 模拟“视觉只读”(比如灰掉+禁止 pointer),必须配合
pointer-events: none和tabindex="-1",否则键盘仍可切换
disabled 与 checked 可共存,但提交时被忽略
一个 radio 同时有 disabled 和 checked 是合法的,页面会显示为已选中但不可操作。这点常被误认为“失效”,其实是预期行为。关键影响在于表单提交逻辑:
- 如果用户原本选中的是某个 radio,之后你 JS 设置它为
disabled,它的checked状态还在 DOM 里,但 POST/GET 数据中**完全不出现该字段** - 若需保留值但禁止修改,得换思路:改用隐藏域
<input type="hidden" name="xxx" value="val">,再把 radio 组全部disabled - 不要依赖
:disabled:checkedCSS 伪类做状态提示——部分旧版 Safari 对该组合支持不稳定
用 fieldset + disabled 实现语义化批量控制
比逐个操作 radio 更简洁可靠的方式,是把它们包进 <fieldset></fieldset> 并对 fieldset 设置 disabled。此时所有内部表单控件(包括 radio)自动继承禁用行为,且语义清晰。
示例结构:
- 注意:IE9+ 和所有现代浏览器均支持 fieldset 的
disabled,无需 polyfill - fieldset 禁用后,其
<legend></legend>文字默认变灰,但部分浏览器(如 Firefox)不会应用opacity,需额外 CSS 统一视觉 - 不能嵌套
fieldset disabled来“局部启用”子项——子项仍被禁用,无例外
想“只读但提交值”?别硬改 radio,用隐藏域 + 视觉锁定
这是实际业务中最容易卡住的点:设计要求“用户不能改,但值要传上去”。radio 本身做不到,强行 hack 会导致表单逻辑错乱或无障碍访问失败。
- 正确做法是移除所有 radio 的
name(避免参与提交),添加一个同名<input type="hidden">存当前值 - 用 CSS 把 radio 组设为
opacity: 0.6; pointer-events: none;,并确保tabindex="-1"阻止键盘焦点 - 如果值来自后端,隐藏域 value 应由服务端直接输出,而非靠 JS 读取 disabled radio 的 checked 状态——那状态可能已被用户脚本篡改
- 辅助技术(如屏幕阅读器)仍可能朗读 radio 标签,建议加
aria-hidden="true"配合视觉隐藏
禁用和只读在表单语义上根本不是一回事;radio 的限制很死,绕不开就得换承载方式。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











