:required 本身不显示红星,因它仅匹配带 required 属性的元素而不渲染样式;需用 label:has(> input:required)::after 等 css 方案或内联 * 实现,兼顾兼容性、可访问性与表单验证联动。

为什么 :required 本身不显示红星
:required 只是匹配带 required 属性的表单元素(如 <input required>),它不负责渲染样式。要加红星,必须配合伪元素或额外内容——浏览器不会自动插入 *。
用 ::after 在 label 后添加红星最稳妥
直接给 input:required 加 ::after 无效(<input> 是替换元素,不支持伪元素内容);正确做法是定位到关联的 label,且确保 label 显式绑定 for 或包裹 input:
- 写法示例:
label:has(> input:required), label[for]:has(input:required) { position: relative; } label:has(> input:required)::after, label[for]:has(input:required)::after { content: " *"; color: #e32; font-size: 1.1em; vertical-align: top; } -
:has()是关键,但注意:Chrome 105+、Firefox 120+、Safari 15.4+ 支持;旧版需回退到 JS 注入类名或手动加class="required" - 避免用
input + label::before,因为 DOM 顺序不一定保证label紧邻input
兼容性差时用 HTML 内联 * 更可靠
如果项目需支持 IE 或老版 Safari,别依赖 :required 动态加星,改用静态标记:
- 在
label文本末尾直接写:<label>用户名 <span aria-hidden="true">*</span></label>
- 再用 CSS 控制视觉:
label span[aria-hidden="true"] { color: #e32; } - 同时保留
required属性做表单校验,语义和功能不丢失 - 这样既满足无障碍(
aria-hidden防止屏幕阅读器重复读“星”),又无 CSS 兼容问题
别忽略可访问性和表单验证联动
纯视觉红星容易让屏幕阅读器用户漏掉必填提示,也容易和后端校验脱节:
- 确保每个
input:required都有明确的aria-required="true"(尽管required属性本身已隐含该语义,但部分旧读屏器仍需显式声明) - 提交失败时,仅靠红星不够——要用
:invalid+outline或背景色强化错误状态,例如:input:required:invalid { outline: 2px solid #e32; } - 如果用了 JS 动态切换
required,记得同步更新label上的红星逻辑(CSS:has()会响应,但旧方案需手动 toggle 类)
:has() 方案越来越可行,但只要团队还要维护 Safari 15.3 以下版本,内联 * 仍是更少意外的选择。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











