HTML标准规定ol的直接子元素只能是li,因此radio必须置于li内;正确做法是用label包裹radio并设相同name属性,既保持语义又确保互斥选择。

ol 里不能直接放 <input type="radio"> 当列表项
HTML 标准规定 <ol></ol> 的直接子元素只能是 <li>,而 <li> 内部可以放任何流内容(包括表单控件),但浏览器不会自动把 radio 按顺序编号 —— 你看到的序号来自 <ol></ol> 的计数器,和 radio 无关。强行把 <input> 塞进 <li> 没问题,但“编号 + 单选”是两件事,得分开处理。
用 <li> 包裹 radio,并保留 ol 的语义和样式
正确做法是让每个 <li> 包含一个 <label></label>,里面放 <input type="radio"> 和文本。这样既保持了有序列表的语义(适合屏幕阅读器、SEO),又能正常交互。
<ol> <li><label><input type="radio" name="choice" value="a"> 选项一</label></li> <li><label><input type="radio" name="choice" value="b"> 选项二</label></li> <li><label><input type="radio" name="choice" value="c"> 选项三</label></li> </ol>
- 必须为所有 radio 设置相同的
name属性,否则无法互斥选择 -
<label></label>包裹 input 可点击区域更大,且点击文本也能选中 radio - 不要给
<input>加id再用for关联 —— 包裹方式更简洁、不易出错
如果需要自定义编号样式(比如加圆圈、箭头),别动 <ol></ol> 的 type
<ol type="A"></ol> 或 <ol start="2"></ol> 只控制数字/字母序列,不影响 radio 行为。真要改视觉效果,用 CSS 计数器更可控:
ol.custom-radio {
counter-reset: item;
}
ol.custom-radio li {
counter-increment: item;
}
ol.custom-radio li::before {
content: counter(item) " → ";
font-weight: bold;
margin-right: 8px;
}
- 避免用
list-style-type: none+ 手动写编号,会丢失语义和可访问性 - CSS 计数器不影响
<input>的功能,radio 依然按原逻辑工作 - 注意:某些旧版 Safari 对
::before在<li>上的支持有边界情况,建议测试
常见错误:用 <div> 替换 <code><ol></ol> 或用 <ul></ul> 模拟序号
有人为了“方便加 radio”直接弃用 <ol></ol>,改用 <div> + 手动写 “1. 2. 3.”,这是退化语义。后果包括:<ul>
<li>屏幕阅读器读不出“这是第几个选项”,只当普通段落</li>
<li>复制整段文字时,编号变成纯文本(如 “1. 选项一”),无法被程序解析结构</li>
<li>打印或高对比度模式下,手动编号可能错位或丢失</li>
<li>
<code><ul></ul> + list-style-type: decimal 是伪序号,不具 <ol></ol> 的语义权重
真正难的不是怎么放 radio,是怎么让机器和人都明白“这是带顺序的单选组”——<ol></ol> + <li> + <input type="radio"> 这个组合,就是目前最稳妥的表达方式。











