input type="radio" 是唯一能兼顾可访问性、表单提交和无 js 回退的起点,因其语义明确、键盘操作原生支持、值可被序列化提交;div+css 方案存在屏幕阅读器无法识别、键盘不可操作、表单不提交三大缺陷。

input type="radio" 是唯一能兼顾可访问性、表单提交、无 JS 回退的起点,其他方案(div+JS、input type="range")在语义、键盘操作或无障碍支持上都有硬伤。
为什么不能直接用 div + CSS 画星星?
看似灵活,实则埋了三个雷:
• 屏幕阅读器读不出“这是评分控件”,aria-label 补不全语义缺失
• 键盘用户无法用 Tab 进入、空格选中,tabindex="0" 加了也难模拟 radio 的互斥逻辑
• 表单提交时,div 的值根本不会被序列化发送,后端收不到 rating=4
真正需要交互+提交的场景,绕开 input type="radio" 就是给自己加测试负担。
label 必须包住 input,而不是靠 for/id 绑定
结构上推荐这种写法:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
<label><input type="radio" name="rating" value="5"> ★</label>而不是分开写
input 和带 for 的 label。原因很实际:• 点击区域更大:整个
label 内容(包括文字、图标)都可触发,移动端更友好• 不用担心
id 冲突或拼错——没 id 就没这问题• CSS 里可以直接写
input:checked + label::before 或 input:checked ~ label::before,选择器更稳• 隐藏
input 时,position: absolute; opacity: 0; 要加在 input 上,别误加到 label 上导致点击失效
悬停高亮和已选状态的 CSS 顺序不能错
三类状态必须按这个顺序写 CSS:
• input:hover + label::before(鼠标划过某颗星,它及左边所有星高亮)
• input:focus + label::before(键盘聚焦时轮廓+颜色,需同时设 outline)
• input:checked ~ label::before(已选中后保持实心,必须放最后,否则会被前面覆盖)
常见翻车点:
• 用 + 而不是 ~:如果 label 不紧跟在 input 后面(比如中间有注释或空格),+ 就找不到目标
• 忘了 direction: rtl:不设这个,CSS 里想让“5星在右、1星在左”,就得手动反转 DOM 顺序,维护成本高
• 移动端没加 :active:iOS Safari 的 :hover 基本不触发,得补 input:active + label::before 保点击反馈
半星要 JS,但别一开始就写
纯 CSS 实现不了真半星——因为 input 的 value 只能是整数,:checked 无法表达 4.5。真实项目里:
• 先用 input type="radio" 把整星逻辑跑通,确保表单能提交、读屏能朗读、键盘能操作
• 半星作为增强层:监听鼠标 move,算出相对位置,动态加 class 或改伪元素 clip-path,再把计算值存在 data-rating 里供 JS 读取
• 注意降级:JS 失败时,回退到最近的整星(比如用户拖到 4.7,就自动记为 5)
别为了“看起来高级”在第一版就堆半星,可访问性和表单可靠性永远优先于视觉精度。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










