星星评分组件必须用<input type="radio">实现,通过DOM顺序+~选择器控制样式、label关联保障可访问性,禁用display:none隐藏、row-reverse布局及checkbox替代。

星星组件必须用 <input type="radio"> 实现可选性
纯 CSS 实现评分交互,核心是利用 radio 的单选特性和相邻兄弟选择器(~)或父容器状态联动。不能用 checkbox 或 button 替代,否则无法原生捕获“选中值”且难以绑定表单提交。
常见错误是直接用 div + click 事件模拟,结果导致:表单不收集值、键盘不可访问(Tab/Space 无法操作)、屏幕阅读器识别失败。
- 每个星星对应一个
<input type="radio">,name相同,value为 1–5 - 隐藏原生
input(用position: absolute; clip: rect(0 0 0 0);,不用display: none,否则失去可访问性) - 用
label[for]或将input包在label内,确保点击文字/图标都能触发
用 :checked ~ 控制已选及之前星星的样式
CSS 里不能反向选择“前面的兄弟”,所以必须把 input 放在对应星星标签之前,靠 ~ 向后影响后续星星 —— 这决定了 HTML 结构顺序不能颠倒。
例如:要让选中 value="3" 时,第 1~3 颗星高亮,第 4~5 颗灰显,就得让第 1 颗星的样式受 input[value="1"]:checked ~ .star、input[value="2"]:checked ~ .star、input[value="3"]:checked ~ .star 共同影响。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
- 结构必须是:
input[value="1"]→label.star→input[value="2"]→label.star→ … - 每颗星的
label要紧接在对应input后面,否则~无法命中 - 用
label::before渲染星号图标(推荐使用 Unicode\2605),比图片更轻量、缩放无损
tabindex 和 aria-label 是可访问性的底线
仅靠 CSS 交互,键盘用户会卡住:按 Tab 能聚焦到 input,但 Space/Enter 不触发切换 —— 因为 radio 默认只响应点击,不响应空格键切换(除非加 role="radio" 并手写 JS,太重)。稳妥做法是保留原生行为,并补全语义。
- 给最外层容器加
role="radiogroup"和aria-label="评分" - 每个
input加aria-label="评分为 3 星"(动态生成) - 避免给
label或星星图标加tabindex="0",否则会多出不可控焦点项 - 测试方式:浏览器开启朗读,Tab 切换,确认能听到“评分,选项 3 星,已选中”
不要用 flex-direction: row-reverse 简化结构
有人想把星星视觉右对齐,就给容器设 flex-direction: row-reverse,再把 input 顺序反过来。这会导致两个问题:一是 ~ 选择器失效(DOM 顺序没变,视觉变了);二是屏幕阅读器仍按 DOM 顺序朗读“5 星、4 星、3 星…”,与用户看到的“1 星在左、5 星在右”冲突。
- 视觉右对齐应通过
justify-content: flex-end或margin-left: auto实现 - DOM 顺序必须保持 1→2→3→4→5,保证语义和样式逻辑一致
- 如果真需要从右往左评分(如 RTL 页面),应整体设
dir="rtl",由浏览器自动处理布局和阅读顺序
input 必须有 id 且与 label[for] 严格匹配,哪怕你用了包裹写法;另外,服务端接收时只认 name 对应的 value,前端 JS 若额外监听 click,反而可能干扰原生表单行为。


















