:required本身不显示红星,因为它仅匹配带required属性的表单控件,不触发任何样式渲染;需配合label:has(input:required)::after等伪元素手动插入星号,并兼顾可访问性与浏览器兼容性。

为什么 :required 本身不显示红星
:required 只是匹配带 required 属性的表单控件(如 <input required>),它不负责渲染任何视觉样式。想加红星,得配合 ::after 或 ::before 伪元素,且目标元素必须支持伪元素——但注意:<input> 是替换元素,默认不支持 ::before/::after(除非设为 display: inline-block 或类似值,但有兼容性和布局风险)。
推荐做法:用 label 包裹 + label:has(input:required)
现代浏览器(Chrome 105+、Firefox 119+、Safari 15.4+)支持 :has(),可精准定位「包含必填 input 的 label」,再在 label 后插入红星。安全、语义清晰、无需 JS。
- 确保 HTML 结构是
<label><input required>姓名</label>或<label for="name">姓名</label><input id="name" required> - 使用
label:has(input:required)::after添加内容,避免污染 input 本身 - 设置
content: "*"、color: red、margin-left: 4px控制位置和颜色 - 为防屏幕阅读器误读,加
aria-hidden="true"到伪元素(实际需靠 CSS 实现,见下例)
label:has(input:required)::after {
content: "*";
color: #e32;
margin-left: 4px;
font-size: 1.2em;
vertical-align: middle;
}
兼容旧浏览器的 fallback 方案
如果要支持 Chrome 104–、Safari 15.3–,不能依赖 :has()。此时需在 HTML 中显式标记必填项,比如给 label 加 class="required",或用 data-required 属性:
- 写法一:
<label data-required>邮箱</label><input required>→ 用label[data-required]::after - 写法二:
<label class="required">手机号</label>→ 更可控,不依赖 JS 或属性同步 - 避免用
input:required + label,因为 label 很少紧跟 input,相邻兄弟选择器极易失效 - 若 label 在 input 前,可用
label[for] + input:required配合 JS 动态加 class,但纯 CSS 更稳
容易被忽略的细节
红星不是装饰,它承担可访问性职责。光加星号不够:
立即学习“前端免费学习笔记(深入)”;
- 必须确保 label 文本本身明确表达“必填”,例如“姓名 *”或“邮箱(必填)”,不能只靠星号暗示
-
::after插入的内容默认会被屏幕阅读器朗读,若不想重复播报“星号”,需用content: "*"; speak: none;(部分浏览器支持)或改用背景图 - 表单重置(
<button type="reset">)后,:required状态不变,但用户可能误以为已清空必填逻辑——这属于交互设计范畴,CSS 无法解决 - 某些 UI 库(如 Ant Design、Element Plus)会自己处理必填标记,直接覆盖其 CSS 前务必检查是否已有
.ant-form-item-required类


















