先记住这个答案
:required 匹配 HTML 中写了 required 属性的表单控件,比如 <input required>。:optional 刚好相反,匹配没有写 required 的。这两个伪类只看属性有没有,和用户有没有填内容没关系。用它们可以在纯 CSS 里区分必填项和选填项的视觉样式。
:required匹配有required的控件:optional是:required的取反- 和用户输入无关,只看 HTML 属性
:optional表示控件无需填写
给必填项和选填项不同的样式
表单设计中,必填项通常用红色星号或加粗边框来提醒用户。以前要在 HTML 里手动加类名或在 JavaScript 里判断,现在直接用 :required 和 :optional 就行。
/* 必填项左边加一条红色竖线 */
input:required {
border-left: 3px solid #e74c3c;
}
/* 选填项用默认边框 */
input:optional {
border-left: 3px solid #ddd;
}只要 HTML 里写了 <input required>,左边就会自动出现红色竖线。不需要 JavaScript,也不需要额外的类名。动态用 JavaScript 添加或移除 required 属性时,样式会实时更新。
和其他验证伪类配合使用
:required 经常和 :valid、:invalid 搭配,实现更细致的验证反馈。比如必填项为空时显示红色,填了有效内容后变绿色。
/* 必填且为空(无效) */
input:required:invalid {
border-color: #e74c3c;
}
/* 必填且有效 */
input:required:valid {
border-color: #2ecc71;
}
/* 选填且有效 */
input:optional:valid {
border-color: #95a5a6;
}:required:invalid 在页面加载时就会匹配(因为空的必填项天然无效),这可能会让用户还没开始填就看到一片红色。解决办法是加上 :not(:placeholder-shown) 条件,只有用户开始输入后才显示验证状态。或者用 :focus 来限制只在聚焦时才变色。
适用范围和限制
:required 和 :optional 只对表单控件生效,具体是 <input>(大多数类型)、<select> 和 <textarea> 这三类元素。<input type="hidden"> 和 <input type="range"> 虽然也是 <input>,但 required 属性对它们没有实际的验证约束意义。
给 <div> 或 <span> 加 required 属性不会让它匹配 :required,因为这些元素不是表单控件,浏览器不会把 required 当作有效属性来处理。
容易答错的地方
- 以为 required 跟用户输入有关
:required只看 HTML 属性,和输入框里有没有内容完全无关。一个<input required>即使用户已经填了内容,:required依然匹配。要根据有没有填内容来区分,应该用:valid和:invalid。- 以为 optional 是默认样式的意思
:optional不是「没有任何伪类匹配」的意思,它是主动匹配没有required属性的表单控件。如果你写了input:optional { ... }的样式,它会应用到所有非必填输入框上。
面试官还会怎么问?
用 JavaScript 动态添加 required 属性后,伪类会更新吗?
会。:required 和 :optional 实时跟踪 DOM 属性。用 element.setAttribute('required', '') 或 element.required = true 添加属性后,样式会立刻从 :optional 变成 :required。
怎么避免页面一加载必填项就显示红色?
用 :user-invalid 伪类代替 :invalid。:user-invalid 只在用户实际和表单交互过之后才匹配(比如输入又删除、或者点过提交按钮),避免了页面加载时就满屏红色的问题。不过 :user-invalid 浏览器支持较晚,兼容性不够时可以用 :not(:placeholder-shown):invalid 来近似实现。
select 元素怎么判断 required?
<select required> 时,如果当前选中的 <option> 的 value 是空字符串,就匹配 :invalid。通常的做法是第一个 <option> 写成 <option value="">请选择</option>,这样用户没选时就是无效状态。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。