readonly 对 checkbox/radio 无效,浏览器忽略该属性;必须用 disabled 或 css+js 拦截实现禁用,但 disabled 会导致字段不提交,故常需 js 阻止事件并配合服务端校验。

readonly 对 checkbox/radio 实际无效
readonly 属性在 <input type="checkbox"> 和 <input type="radio"> 上**不触发只读行为**,浏览器会忽略它。用户依然可以点击切换状态,JS 也能正常修改 checked 属性。这是 HTML 规范明确规定的:只对可编辑的表单控件(如 text、textarea)生效。
- 现象:加了
readonly的 checkbox 仍能点选,控制台查element.readonly返回true,但行为完全没变 - 原因:规范里
readonly只影响“文本输入能力”,而 checkbox/radio 的交互本质是状态切换,不是内容编辑 - 替代方案只能用
disabled或 JS 拦截,但二者语义和表现完全不同
disabled 是唯一原生有效方案,但有副作用
想真正禁用 checkbox/radio 的交互,必须用 disabled。但它会带来三个硬性变化:
- 视觉上默认变灰、降低透明度(各浏览器略有差异,但都明显弱化)
- 提交表单时该字段**不会被发送**(
name=value直接丢弃) - JS 中
element.checked仍可读写,但表单序列化(如FormData、serialize())完全跳过它
如果你需要“保留值 + 禁止操作”,disabled 就不是正确选择——它牺牲了数据传递能力。
模拟只读:CSS + JS 组合最常用
要实现“看起来可点、实际不能改,且值照常提交”,得手动拦截。核心思路是:用 CSS 去掉手型光标和视觉反馈,再用 JS 阻止默认行为。
- CSS 关键样式:
pointer-events: none;(禁鼠标事件),配合cursor: default;避免误导 - JS 必须监听
click并调用event.preventDefault(),否则 Safari 等浏览器可能仍响应 - 注意:不要只靠 CSS,否则键盘
Space切换仍有效;必须同时处理keydown(监听空格/回车) - 示例最小拦截:
input[readonly][type="checkbox"], input[readonly][type="radio"] { pointer-events: none; cursor: default; }+input.addEventListener('click', e => e.preventDefault())
服务端必须校验,前端只读全是障眼法
无论用 disabled、pointer-events: none 还是 onclick="return false",都只是客户端限制。真实请求中,攻击者可直接构造 POST 数据绕过所有前端防护。
- 如果业务逻辑要求某选项“只读不可改”,服务端收到请求后必须比对原始值或校验权限,而非信任前端传来的
checked状态 - 常见坑:把
disabled当作安全手段,结果表单里漏传字段,后端又没兜底校验,导致数据错乱 - 更稳做法:后端存一个“只读字段白名单”,请求到达时先检查该字段是否允许更新,再决定是否应用新值
视觉上怎么让它像只读,是次要问题;服务端敢不敢信这个值,才是关键分水岭。











