必须同时使用 :focus 和 :focus-visible 并配合语义属性(id + label),否则键盘用户无法识别焦点;全局 outline: none 会隐藏 tab 焦点,需用双写规则确保视觉反馈与无障碍兼容。

直接改 :focus 不够,必须配合 :focus-visible 和语义属性,否则键盘用户根本看不到焦点在哪。
为什么只写 .form-control:focus 会失效?
现代浏览器默认抑制鼠标点击后的 :focus-visible,只保留 :focus;但如果你全局写了 outline: none 又没补 :focus-visible,那键盘 Tab 焦点就彻底“隐身”了。
- Chrome/Firefox:鼠标点按钮 → 触发
:focus,但不触发:focus-visible - Safari(尤其移动端):对非表单元素的
:focus-visible支持极弱,甚至完全跳过 - 如果用了 Bootstrap 的
reboot.scss或自定义重置,大概率已清掉了outline,必须手动补救
:focus 和 :focus-visible 怎么共存才安全?
别二选一,要双写,且优先级明确:让 :focus-visible 覆盖鼠标点击后“不该出现”的焦点环,同时确保键盘 Tab 必定触发视觉反馈。
- 写法示例:
.form-control:focus, .form-control:focus-visible { outline: none; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); border-color: #86b7fe; } - 必须加
outline: none,否则原生 outline 和 box-shadow 叠在一起难看又难对齐 - 别只用
box-shadow而忽略border-color,否则在高对比度模式下可能丢失边界识别 - 深色模式下
rgba(13, 110, 253, 0.25)太淡,建议改成rgba(13, 110, 253, 0.4)或用 CSS 变量动态切换
表单控件必须带 id + label 关联,否则焦点样式白配
无障碍焦点不只是视觉问题——屏幕阅读器靠 label 和 id 绑定来播报字段含义。没有这个绑定,即使样式再亮,用户也不知道当前聚焦的是“邮箱”还是“密码”。
- 正确写法:
<label for="email">电子邮箱</label> <input type="email" id="email" class="form-control">
- 禁用
for/id匹配(比如用aria-label替代)时,必须确保aria-label值明确、无歧义,且不能和 placeholder 冗余 - Bootstrap 的
.form-label类本身不提供关联逻辑,只是样式,for和id缺一不可 - 自定义 select 或日期控件(如
bootstrap-datepicker)需额外补aria-labelledby,否则焦点进入日历面板后阅读器会失焦
真正容易被忽略的不是阴影大小或颜色,而是 tabindex 值和 aria-hidden 的联动——模态框打开时若没设 aria-hidden="true" 给背景,键盘用户仍能 Tab 到隐藏区域,焦点样式就会出现在不可见元素上,造成逻辑断裂。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











