bootstrap 5 表单验证边框需通过 .form-control.is-invalid 类控制,而非 :invalid 伪类;必须配合 novalidate 属性、js 手动增删类,并覆盖聚焦/禁用/只读等状态,深色模式下还需调整颜色与阴影。

直接改 .form-control.is-invalid 才生效,别碰 :invalid 伪类
写 .form-control:invalid { border-color: #dc3545; } 基本没用。Bootstrap 5 的验证边框颜色不是靠浏览器原生伪类驱动的,而是依赖显式添加的 is-invalid 类。这个类必须由 JS 手动加到输入框上,CSS 才能匹配并渲染。:invalid 只在 novalidate + was-validated 同时存在时才参与计算,但权重低、兼容差(尤其 iOS Safari),不推荐作为主路径。
.form-control.is-invalid 必须覆盖所有相关状态
只写一条规则远远不够。输入框在验证失败后仍可能被聚焦、禁用或只读,这些状态下的边框会被更高优先级的默认样式覆盖。必须同步处理:
-
.form-control.is-invalid:基础失败态 -
.form-control.is-invalid:focus:聚焦时不能回退成蓝色边框 -
.form-control.is-invalid:disabled和.form-control.is-invalid[readonly]:避免禁用态边框变灰或消失
每条都得加 !important,否则 Bootstrap 原生 CSS(含 [class*="is-invalid"] 这类高权重选择器)会压住你。
结构和 JS 同步不到位,CSS 再对也白搭
常见现象是样式写了、类名也加了,但边框还是默认红色或根本不变——问题出在 DOM 结构或 JS 控制链上:
-
<form></form>标签漏了novalidate属性,浏览器原生弹窗抢走焦点,is-invalid类加了也看不到效果 - 校验失败后只调
input.setCustomValidity('msg'),但没执行input.classList.add('is-invalid') - 成功校验后没清理旧状态:
input.classList.remove('is-invalid', 'is-valid'),残留类导致样式错乱 - 用了
form-floating,但<input>和<label></label>之间插了空格或注释,破坏了兄弟选择器上下文(虽然不影响边框,但容易连带误判)
深色模式下边框颜色容易对比度不足
如果你项目启用了 data-bs-theme="dark",默认的 #dc3545 在深灰背景上可能发暗、难识别。不要硬套浅色模式值。建议:
- 用 CSS 变量动态适配:
border-color: hsl(0 69% 58%);(比纯红更亮) - 或检测主题后覆盖:
html[data-bs-theme="dark"] .form-control.is-invalid { border-color: #ff6b6b; } - 别忽略
box-shadow:聚焦时默认阴影色(rgba(220,53,69,0.25))在暗背景下可能不可见,需一并调整 alpha 或色相
真正卡住人的从来不是怎么写 CSS,而是忘记 novalidate 是开关、is-invalid 是钥匙、JS 同步是锁芯——三者缺一,边框就亮不起来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











