:required 和 :optional 是表单可读性的基础层,直接映射 HTML required 属性状态,通过 CSS 创建视觉权重梯度(如必填项凸出、可选项弱化)实现“秒懂”区分,依赖语义标注准确性和原生属性存在性,不兼容自定义组件或属性拼写错误。

:required 和 :optional 不是装饰性技巧,而是表单可读性的基础层 —— 它们直接映射 HTML 的 required 属性状态,无需 JS 就能建立视觉契约。
为什么用户会漏填或犹豫?因为“必填”和“可选”在视觉上没拉开差距
很多表单把所有字段用同一套边框、背景、字体渲染,用户得逐个读 label 或 placeholder 才能判断是否必须填。尤其在移动端小屏上,这种认知负担明显上升。:required 和 :optional 的价值,就是把“HTML 层面的约束”翻译成“眼睛能秒懂的样式差异”。
- 浏览器原生只做提交拦截,不提供视觉提示 —— 这块空白必须由 CSS 填补
- 仅靠 * 星号标记不可靠:它可能被遮挡、缩放后看不清、或与 label 对齐错位
- 如果所有字段都加了
required,那:required就失去区分意义 —— 它依赖合理的语义标注
怎么写才真正起效?重点不是颜色,而是视觉权重梯度
单纯改 border-color 或 background 很容易流于表面。真正提升体验的关键,是让必填项“往前跳”,可选项“往后退”。比如:
-
input:required用实色粗边框 + 稍亮背景 + 字体加粗,制造轻微“凸出感” -
input:optional用 0.85 透明度 + 虚线边框 + 浅灰背景,降低存在感但不消失 - 避免对
input[type="hidden"]或input[type="submit"]使用这两个伪类 —— 它们本就不参与用户输入,匹配无效 - 别在
input:required::after里加content: "*"—— 大多数现代浏览器对input元素的伪元素支持不稳定,推荐改用 label 包裹或 JS 注入
哪些场景下它们会失效?关键看 HTML 是否干净
这两个伪类完全依赖 required 属性是否存在,不关心值是否为空、也不校验类型。常见失效点:
立即学习“前端免费学习笔记(深入)”;
- 写了
required="false"—— 这不是布尔属性,只要出现就等价于required,仍会被:required匹配 - 动态移除
required属性但未触发重绘(比如用 JS 切换却忘了强制 reflow)—— 样式不会自动更新 - 用了自定义组件(如封装的
<MyInput>),但内部没透传required属性到原生input—— 伪类根本选不到 - 表单字段用了
disabled或readonly—— 它们仍会被:optional匹配,除非显式加了required
兼容性不是问题,但要注意 Safari 对 :optional 的早期版本处理
Chrome/Firefox/Edge 自 v57+、Safari 自 v15.4+ 都已完整支持。唯一要注意的是 Safari 14 及更早版本会忽略 :optional,但会正确识别 :required —— 所以如果你的用户仍有 Safari 14 流量,建议用 input:not([required]) 作为降级方案,效果一致且兼容性更好。
真正容易被忽略的,是伪类生效的前提:它只作用于原生表单控件,且依赖属性是否“存在”,而不是“值是否为真”。写样式前,先检查你的 input 标签里有没有多余的空格、引号或拼写错误 —— 比如 requred 或 require,这种 typo 会让整个视觉逻辑崩掉。


















