:required和:optional仅匹配HTML中是否存在required属性,不反映用户填写状态;仅对支持原生验证的控件生效,如text、email、select、checkbox、radio等,而hidden、button、submit等无效。

:required 和 :optional 不反映用户是否填了内容,只看 HTML 里有没有写 required 属性。用错就白写了——比如你靠 JS 动态加 required,但没触发浏览器重绘,样式可能不生效;或者误以为 :optional 能匹配 <button></button> 或 <div>,结果样式根本不起作用。
<h3>哪些元素能被 <code>:required 匹配?
只有显式带 required 属性、且本身支持原生表单验证的控件才生效:
-
<input type="text" required>→ ✅ 匹配 -
<select required></select>→ ✅ 匹配(哪怕第一个<option></option>是空值且selected) -
<textarea required></textarea>→ ✅ 匹配 -
<input type="checkbox" required>→ ✅ 匹配(注意:单个 radio 组中只有带required的那个<input>被选中,不是整组) -
<input type="hidden" required>→ ❌ 不匹配(type="hidden"被排除在验证流程外) -
<button required></button>→ ❌ 不匹配(<button></button>不参与提交校验)
:optional 的边界容易踩坑
:optional 不是“所有没写 required 的标签”,而是“没写 required 且支持验证”的控件。这个条件漏掉就全乱了:
-
<input name="phone">→ ✅ 匹配:optional -
<input type="number" min="18">→ ✅ 匹配(有验证逻辑但没标必填) -
<input type="file" name="avatar">→ ✅ 匹配(支持验证,没required就算 optional) -
<div><input name="fake"></div>→ ❌ 不匹配(<div> 不是可提交控件,CSS 选择器不穿透) <li> <code><fieldset required></fieldset>→ ❌ 不匹配(<fieldset></fieldset>本身不参与验证) -
input:required:invalid→ 只在字段为空或格式错误时生效(需配合type或pattern) -
input:required:focus→ 可叠加聚焦态样式,但不能替代:invalid做校验反馈 - 不要写
input:required[value=""]→value是 DOM 属性,CSS 无法读取,无效 - 避免仅靠颜色区分(如红/灰),加边框粗细、虚实或图标辅助
- 用
label:has(input:required)::after插入*比硬编码更语义化,但注意:has()在 Safari 15.4+ 才稳定 -
input:optional降低透明度时,别低于opacity: 0.6,否则影响可访问性(WCAG AA 级要求)
别指望它们响应填写状态
:required 和 :optional 是静态属性匹配,和用户输没输、输对没输完全无关。想高亮“空但必填”的字段,得组合 :required:invalid;想区分“已填”和“未填”,得用 :placeholder-shown 或监听 input 事件加 class。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
样式建议优先级与兼容性
现代浏览器(Chrome 10+, Firefox 4+, Safari 15.4+)都支持,但 IE 完全不支持。如果要降级,得 fallback 到 class 手动控制:
立即学习“前端免费学习笔记(深入)”;
required 属性都准确对应后端约束,且没有遗漏支持验证的控件类型——比如忘了 <input type="date"> 也属于可匹配范围,或者把 required 错加在 <label></label> 上。

















