可用 :required 和 :optional 实现自动视觉区分,无需 JS 或修改 HTML;硬编码星号导致维护困难且易漏配无障碍属性;伪元素星号应加在 label 上(如 label:has(input:required)::after),并确保 label 正确关联 input。
直接用 :required 和 :optional 就能实现视觉区分,无需 JS、不改 HTML 结构,但必须注意浏览器支持和伪元素限制。
硬写 * 到 HTML 里会导致维护困难:字段状态一变(比如后端动态加 required),前端就得同步改模板;无障碍属性(如 aria-required)也容易漏配。而 :required 和 :optional 完全依赖属性本身,HTML 变,样式自动跟上。
required 属性,input:required 就生效;没写,就归 :optional 管input[type="hidden"]、input[type="submit"] 等非用户输入控件用 ::after 在 label 上加星号比在 input 上更稳妥,因为多数 input 不支持伪元素内容渲染(尤其是 type="text")。
label:has(input:required)::after { content: " *"; color: #e74c3c; }
label 包裹或正确 for/id 关联,否则 :has() 不生效data-required 类作降级:optional 是“未声明 required”的兜底匹配,但容易被开发者忽略两个边界情况:
立即学习“前端免费学习笔记(深入)”;
required 和 disabled,它仍匹配 :required,而非 :optional
input:optional 不会匹配 input[type="radio"] 组中部分项带 required 的情况——整组是否必填,由第一个带 required 的单选框决定required 属性时,需确保属性是真实写入 DOM 的布尔属性,而非字符串 required="false"
单独用 :required 只解决“该不该填”,真正要引导用户的是“没填怎么办”。这时和 :invalid 联动最直接:
input:required:invalid { background-color: #fdf2f2; border-color: #e74c3c; }:invalid 的前提是字段已聚焦过(:user-invalid 更精准,但兼容性差):optional:invalid 当校验逻辑用——可选字段即使填错,也不该强制高亮,除非业务明确要求校验真正难的不是写这几行 CSS,而是统一团队对 required 属性的使用习惯:一个字段该不该标 required,决定了整个视觉链路是否可信。样式只是表达,语义才是根基。