:focus样式未生效主因是元素不可聚焦,需加tabindex="0";Mixin应传入基础选择器避免权重不足;:focus-visible需@supports分层兼容;焦点色须满足3:1对比度。

focus 状态样式为什么没生效
多数时候不是写错了 :focus,而是元素本身不能获得焦点。原生不可聚焦的元素(比如 div、span)默认没有 tabindex,键盘 tab 或 JS 调用 .focus() 都不会触发样式变化。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 给需要高亮反馈的容器加
tabindex="0"(允许键盘聚焦,又不改变语义顺序) - 避免用
tabindex="-1"除非你只打算用 JS 主动聚焦——它不参与 tab 流,:focus仍可触发,但用户无法键盘到达 - 检查是否被
outline: none全局覆盖了,且没补替代样式(这是最常见“写了但看不见”的原因)
用 Less Mixin 封装 focus 样式要避开哪些坑
Mixin 本质是代码复用,但 CSS 焦点状态有特殊性:它依赖伪类层级和 specificity。直接把 :focus 塞进 Mixin 容易导致选择器权重不足,或在嵌套结构中生成错误路径。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- Mixin 参数里显式传入基础选择器,而不是靠父级嵌套推导:
.focus-highlight(@color) {<br> &:focus { outline: 2px solid @color; }<br>}比.focus-highlight() { &:focus { ... } }更可控 - 别在 Mixin 里写
!important——它会污染后续覆盖逻辑;真要强制,用更高 specificity 的选择器,比如&:focus, &.js-focus - 如果组件含子元素(如按钮内有图标),
:focus应作用于可聚焦主体,而非内部元素,否则焦点管理会混乱
focus-visible 与传统 :focus 的兼容处理
:focus-visible 是现代浏览器对“仅键盘触发 focus”做样式区分的标准方案,但旧版 Safari 和部分安卓 WebView 不支持。直接替换 :focus 会导致鼠标点击后无反馈。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用
@supports分层定义:&:focus { outline: 2px solid #999; }<br>@supports (focus-visible: auto) {<br> &:focus:not(:focus-visible) { outline: none; }<br> &:focus-visible { outline: 2px solid #007bff; }<br>} - Less 中不要用变量模拟
focus-visible的检测逻辑——CSS 特性检测必须由浏览器运行时执行,预编译的 Less 无法替代 - 若项目需兼容 IE,保留
:focus并禁用:focus-visible回退,别试图用 JS 模拟该伪类行为(可靠性差、性能拖累明显)
高亮颜色对比度不够被忽略的实际影响
视觉上“有焦点样式”不等于“符合可访问性要求”。WCAG 2.1 要求焦点指示至少与背景有 3:1 的颜色对比度,否则色弱用户或低亮度设备下根本看不到。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用浏览器 DevTools 的无障碍面板实时测
:focus状态下的对比度,别只凭肉眼判断 - 避免用纯灰阶做焦点色(如
#aaa在浅灰背景上);优先选带色相的高对比色,比如#0066cc或#28a745 - 如果主题色对比度不达标,宁可用双线框(
outline: 2px solid #000; outline-offset: 2px)提升识别度,也别妥协于模糊的浅色描边
真正难的不是写出 :focus 样式,是让每个操作路径(鼠标、键盘、屏幕阅读器)都一致地感知到当前焦点在哪。样式只是表层,背后是交互意图的准确传达。


















