纯HTML+CSS星级评分需用radio单选+label包裹+伪元素绘星,隐藏input用opacity:0,CSS用~选择器和:checked实现点击反馈,语义上高分在右需flex-reverse或RTL控制,仅支持整星单向选择。

用纯 HTML + CSS 实现可点击的星级评分(无 JS)
纯 HTML 能做星级评分,但仅限于「单向选择 + 表单提交」场景,核心靠 和相邻兄弟选择器 ~ 配合 :checked 状态实现视觉反馈。不能实时读取值、不能半星、不能取消选中——这些必须加 JS。
常见错误是直接用 直接对 容易踩的坑是忘记设置 原生 radio 不支持半星和取消, 关键逻辑是:记录鼠标按下时的星数,拖动时动态更新,松开后固化。取消功能本质是判断是否再次点击同一颗星,需要比对 HTML 表单提交时, 常见漏洞是前端限制了 1–5,但攻击者能绕过 HTML 直接 POST 半星值(如 3.5)必须由 JS 拼成字符串传给隐藏 input,后端再解析小数,但要注意浮点精度和四舍五入策略——多数业务其实只需要整数分,强行半星反而增加存储和统计复杂度。
里,且 在 label 内或通过 for 关联name 必须相同,否则无法互斥)要放在对应 后面,才能用 input:checked ~ span 触发样式checked 属性,不是 defaultChecked(那是 React 的)CSS 星级渲染的关键:隐藏 input + 用伪元素画星
设置颜色没用,必须隐藏它,再用 label::before 或 label::after 绘制 ★ 符号。否则用户看到的是原生 radio 按钮,不是星星。label 的 cursor: pointer,导致看起来不可点;或者用 display: none 隐藏 input 后,:checked ~ label 失效(因为 DOM 顺序断了),正确做法是用 position: absolute; opacity: 0; width: 0; height: 0;。
flex-direction: row-reverse 或 float 反转顺序unicode-bidi: bidi-override 和 direction: rtl 控制 ★ 渲染方向,避免文字流干扰label:hover ~ label, label:hover 实现,但注意这会覆盖已选中的状态,需用 input:checked ~ label 优先级更高来兜底用 JavaScript 补全半星、实时反馈和取消功能
click 事件监听必须绑定在 label 或整个容器上,不能只绑 input——因为 input 被隐藏了,用户点不到。event.target 和当前选中值。
:一个满星,一个遮罩层,用 clip-path 或 overflow: hidden + transform: translateX() 截取宽度mousemove 实时计算,性能差;改用 mouseover + 节流,只在进入新星时更新预览touchstart/touchmove/touchend,且防止 click 冒泡触发两次document.querySelector('input[name="rating"]:checked'),而应缓存到组件 state 或 data 属性里,避免重复查询服务端接收和验证 rating 字段的注意事项
rating 是字符串,比如 "3",不是数字。后端收到后必须校验范围(1–5)、类型(整数)、非空,不能直接转 int 后运算。rating=999 或 rating=abc,后端不校验就可能崩掉数据库或暴露逻辑。
filter_var($rating, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 5]])
parseInt(req.body.rating, 10) 后立刻判断 isNaN() 和边界required 属性——它只在浏览器前端生效,禁用 JS 后无效value="" 的 radio 或单独的“跳过”按钮,不能留空
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











