前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS :valid :invalid :user-valid 区别
HTML表单与输入

:valid 和 :user-valid 有什么区别?为什么一打开页面输入框就是红色的?

:invalid 在页面加载时就会匹配空的 required 输入框,所以还没操作就看到红色边框。:user-invalid 只在用户真正修改过或提交过表单之后才匹配,体验更合理。

前端进阶之旅 · 一题精讲更新于 2026.09.29
HTML#表单与输入#表单
先看核心答案读代码示例
理解线索

两类校验伪类的触发时机

  1. :invalid只看当前值是否满足约束,页面一打开就判定
  2. :user-invalid还要求用户已经改过值或尝试过提交,才开始匹配
  3. :in-range专门针对 min 和 max,值在范围内匹配,超出匹配 :out-of-range

需要兼容旧浏览器时先核对 :user-valid 和 :user-invalid 的支持情况;回退样式要保留可识别的错误提示,不能只靠边框颜色。

核心回答

先记住这个答案

:valid 和 :invalid 只看当前值是否满足 HTML 约束(required、pattern、min、max 等),页面一加载就判定。所以一个空的 required 输入框,用户还没碰就会被 :invalid 匹配到。:user-valid 和 :user-invalid 多了一个前提:用户必须已经修改过这个控件的值,或者尝试过提交表单,伪类才开始生效。这样就能做到「用户改过再提示错误」,不需要写 JS。

  • :valid 和 :invalid 页面一加载就生效
  • :user-invalid 在交互后提示错误
  • min、max 范围用 :in-range 判断
  • 不用 JS 就能实现「先别报错,改过再说」的体验

页面加载时就标红的问题

想象一个注册表单,邮箱框加了 required。如果你用 :invalid 给它加红色边框,用户刚打开页面就看到一个红框,还没来得及输入就被「批评」了。这就是 :invalid 的问题:它不关心用户有没有交互过。

对比两种伪类的效果CSS
/* 不同时启用 input:invalid 的红框,否则初始空值仍会标红 */
input:user-invalid {
  border-color: red;
}

/* 用户交互后且值有效时才变绿 */
input:user-valid {
  border-color: green;
}

:user-invalid 的判定逻辑是:值不满足约束,并且用户已经与这个控件交互过(改过值、失去过焦点,或者点过提交按钮)。两个条件同时满足才匹配。

数字和日期的范围校验

对于 <input type="number"> 或 <input type="date"> 这类有 min 和 max 的输入,CSS 还提供了 :in-range 和 :out-of-range 两个伪类。它们和 :valid 类似,也是页面加载就判定的,但只关心值是否在范围内,不管 required 这些其他约束。

给超出范围的值加提示色HTML
<style>
  input:in-range { background: #e8f5e9; }
  input:out-of-range { background: #ffebee; }
</style>
<input type="number" min="1" max="100" value="150" />
<!-- 因为 150 超出了 max=100,背景色会变成浅红 -->

这里的 value="150" 一加载就超出了范围,所以 :out-of-range 立刻匹配。用户改成 50 之后就切换到 :in-range。

回答前,多想一步

容易答错的地方

以为 :user-valid 只是 :valid 的别名
两者的判定逻辑完全不同。:valid 只看值,:user-valid 还看用户有没有交互过。一个空的 required 框,:valid 不匹配,:user-valid 也不匹配,但原因不一样:前者是因为值不满足约束,后者是因为用户还没交互。
把 :out-of-range 和 :invalid 混为一谈
一个 <input type="number" min="1" max="100"> 如果值为空,:invalid 不匹配(没有 required 所以空值合法),:out-of-range 也不匹配(空值不算超出范围)。只有用户填了一个超出 min 或 max 的数字,:out-of-range 才匹配。
试着用自己的话回答

面试官还会怎么问?

不支持 :user-valid 的老浏览器怎么办?

可以给输入框加一个 interacted 的 class。按产品确定的时机监听 blur 或 input,交互后添加 class,再用 .interacted:invalid 写样式。这是自定义的提示时机,不保证和浏览器的 :user-invalid 判定完全一致;要特别测试用户未输入就离开、提交失败和重置表单三种情况。

:valid 能匹配整个 <form> 吗?

可以。:valid 作用在 <form> 上时,只有表单内所有控件都满足约束,form:valid 才匹配。任何一个控件不满足,form:invalid 就会匹配。这可以用来控制提交按钮的样式。

用 novalidate 关掉校验后,这些伪类还生效吗?

novalidate 只阻止浏览器在提交时弹出校验气泡,不影响伪类的匹配。加了 novalidate 的表单里,:invalid 和 :user-invalid 照常工作,样式正常生效。

从一道题,走向一组知识

把知识连起来

表单与输入

datalist 给输入框提供建议,能限制用户只能选这些吗?

<datalist> 提供的建议也会影响校验状态,两者搭配时需要注意 :valid 的匹配时机。

表单与输入

datetime-local 的值为什么没有时区?

日期输入有 min 和 max 约束,正好用 :in-range 和 :out-of-range 来做样式反馈。

参考资料

  • HTML:表单与输入参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 页面加载时就标红的问题
  3. 数字和日期的范围校验
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑