:required 可直接选中带 required 属性的表单元素,无需提交或 JS 触发;它纯属 CSS 选择器,即时生效,兼容 IE10+,但与 :has() 等搭配时需注意浏览器支持。

怎么用 :required 选中必填表单控件
直接写 :required 就能匹配带 required 属性的 <input>、<select>、<textarea> 元素,不用管它是不是真的被提交校验了——只要 HTML 里写了这个属性,CSS 就认。
常见错误是以为必须配合 JavaScript 或表单提交才能触发样式,其实不是。它纯属选择器,和 :hover 一样即时生效。
-
<input type="email" required>→ 匹配input:required -
<select required>→ 匹配select:required -
<textarea required="required">→ 同样匹配,属性值任意(甚至空字符串)都行
为什么加星号常用 ::after 而不是直接改 content
因为 content 只在伪元素里合法,而表单控件本身不支持 content 属性。想在输入框右侧加 *,得靠 ::after 插入,且目标元素必须是 position: relative 才好定位。
容易踩的坑:忘了设 display: inline-block 或 position: relative,导致 ::after 脱离文档流乱飘;或者给 <input> 直接设 content,完全无效。
立即学习“前端免费学习笔记(深入)”;
- 正确写法:
input:required { position: relative; }+input:required::after { content: "*"; color: red; position: absolute; right: -8px; top: 50%; transform: translateY(-50%); } -
<label>上加星更稳妥:直接写label:has(> input:required)::after(但注意:has()在 Safari 15.4+ 和 Chrome 105+ 才稳定,旧环境慎用)
:required 和 :invalid 混用时样式打架怎么办
:required 是静态标记,:invalid 是动态状态——页面一加载,空的必填项就同时满足两者,这时候 CSS 优先级决定谁胜出。如果都设了 border-color,后声明的会覆盖前一个。
典型问题:想让必填项默认灰边,输错才变红,结果一加载就是红边。原因就是 :invalid 触发太早(空值即无效),且样式权重没控制好。
- 解决办法:用
:required:not(:valid)精确限定“必填但尚未填对”的状态 - 避免全局写
:invalid { border: 1px solid red; },改用input:required:not(:valid) { border-color: red; } - 注意
:valid在用户没输任何内容时为false,所以空必填项天然命中:required:not(:valid)
兼容性与移动端要注意什么
:required 选择器本身从 IE10 开始就支持,没问题;但 :has()、::placeholder 配合使用时,iOS Safari 15.2 之前不支持 :has(),Android WebView 也常滞后。
另一个实际坑点:安卓原生浏览器里,input[type="number"] 的 :required 样式有时不触发,因为某些机型把 required 当作纯校验属性,不参与渲染流程。
- 稳妥方案:降级用 class,比如
<input class="required">+.required,再用 JS 同步增删 class - 移动端测试重点:真机测
input[type="tel"]、input[type="email"],它们在部分 Android 键盘下会自动填充,导致:invalid状态消失得比预期快
:invalid 是否该立即生效;又比如多语言环境下星号该放左边还是右边。这些没法靠一个选择器兜底,得结合交互意图来定。










