正确做法是label必须包裹input,且同组radio的name属性值必须完全一致;避免使用for+id组合及opacity:0隐藏;js获取选中值需判空。

label 必须包裹 input 才能点击文字选中
浏览器只在 <label></label> 显式包裹 <input type="radio"> 时,才把整个文字区域识别为可点击热区。写成分开的 <input> 和 <label for="xxx"></label> 是可行的,但容易漏写 id、拼错、重复,且多一层管理负担。
正确写法就一条规则:文字和控件必须在一个 <label></label> 里。
<label><input type="radio" name="mode" value="auto"> 自动模式</label><label><input type="radio" name="mode" value="manual"> 手动模式</label>
别用 for + id 组合,除非你正在维护一段不能改结构的老代码。
name 属性不统一会导致“看起来能互斥,其实全都能点”
所有同组 radio 的 name 值必须完全一致(包括大小写、下划线/短横线),浏览器才认为它们是一组。漏写、大小写不一致、复制粘贴后没改值,都会让互斥失效。
- ✅ 正确:
name="payment_method"出现在每个<input type="radio">上 - ❌ 错误:
name="payment"、name="PAYMENT_METHOD"、name="paymentMethod"—— 这三者是三组独立按钮 - ⚠️ 注意:HTML 中
name不支持表达式或 JS 变量,必须写死字符串
调试时直接打开 Elements 面板,点一下选项,看对应 <input> 是否真出现 checked="" 属性——没出现,说明根本没被识别为同一组。
JS 读取选中值时,querySelector 返回 null 而不是 undefined
document.querySelector('input[name="theme"]:checked') 是最简方式,但它返回的是 DOM 元素或 null(不是 undefined)。直接链式取 .value 会报 Cannot read property 'value' of null。
- 安全写法:
const el = document.querySelector('input[name="theme"]:checked'); const val = el ? el.value : ''; - 别用
getElementsByName配循环,啰嗦又易错 - 别假设一定有默认选中——用户可能还没点,或者你忘了加
checked,后端也可能收不到这个字段
如果表单提交后后端收不到值,90% 是前端 name 拼错、被 JS 动态改过但没同步、或整组被 <fieldset disabled></fieldset> 包裹了。
样式定制时隐藏原生 radio 要用 clip 而非 opacity: 0
想自定义圆点外观,得先隐藏原生控件。用 opacity: 0 或 visibility: hidden 在移动端 Safari 上可能导致点击响应延迟或失效。
- 推荐隐藏方式:
position: absolute; clip: rect(0, 0, 0, 0); - 再用
label::before或label::after画自定义圆点,并通过input:checked + label::before控制选中态 - 注意:
:checked伪类只作用于input[type="radio"],label本身没有这个状态
真正容易被忽略的点是:即使视觉上完全重绘了,也必须保留原始 <input> 结构和 name/value,否则表单提交或 JS 读取就断了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











