:focus-visible
智能显示焦点环,优化键盘导航体验
什么是 :focus-visible?
:focus-visible 伪类用于选择应该显示焦点指示器的元素。 它解决了传统
:focus 的一个重要问题:当用户用鼠标点击按钮时,
通常不需要显示焦点环,但当用户使用键盘导航时,焦点环是必不可少的。
浏览器会根据用户的输入方式(鼠标、触摸、键盘)智能判断是否需要显示焦点指示器。 这让我们能够在保持良好无障碍访问的同时,提供更清爽的视觉体验。
- 智能判断 - 浏览器根据输入方式决定是否显示焦点环
- 键盘友好 - 使用 Tab 键导航时始终显示焦点指示器
- 鼠标优化 - 鼠标点击按钮时通常不显示焦点环
- 无障碍访问 - 确保键盘用户能清楚看到当前焦点位置
:focus- 元素获得焦点时总是匹配,无论输入方式:focus-visible- 只在应该显示焦点指示器时匹配- 使用
:focus-visible可以避免鼠标点击时出现不必要的焦点环
语法
/* 基础语法 */
element:focus-visible {
/* 只在应该显示焦点指示器时的样式 */
}
/* 推荐的最佳实践 */
button:focus {
outline: none; /* 移除默认焦点环 */
}
button:focus-visible {
outline: 3px solid var(--primary); /* 只在键盘导航时显示 */
outline-offset: 2px;
}
/* 组合使用 */
input:focus-visible {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
- 不要完全移除焦点样式 - 始终为
:focus-visible提供清晰的样式 - 保持高对比度 - 确保焦点指示器在任何背景下都清晰可见
- 使用 outline 而非 border - outline 不会影响布局,更适合焦点指示器
- 添加 outline-offset - 让焦点环与元素保持一定距离,更美观
示例 1: 鼠标点击 vs 键盘导航对比
下面的示例展示了 :focus 和 :focus-visible 的行为差异。
请分别用鼠标点击和键盘 Tab 键来测试按钮的焦点效果。
使用 :focus
无论用鼠标还是键盘,获得焦点时都会显示焦点环
使用 :focus-visible
鼠标点击不显示焦点环,键盘导航时才显示
1️⃣ 用鼠标点击左侧按钮 → 会看到橙色焦点环(不理想)
2️⃣ 用鼠标点击右侧按钮 → 不会显示焦点环(更清爽)
3️⃣ 用Tab 键导航到两个按钮 → 都会显示焦点环(保证可访问性)
/* ❌ 传统方式 - 总是显示焦点环 */
.btn-old-focus:focus {
outline: 3px solid #f59e0b;
outline-offset: 3px;
}
/* ✅ 现代方式 - 智能显示焦点环 */
.btn-new-focus:focus {
outline: none; /* 移除默认样式 */
}
.btn-new-focus:focus-visible {
outline: 3px solid #f59e0b;
outline-offset: 3px;
}
/* 结果:
* - 鼠标点击:不显示焦点环
* - 键盘导航:显示焦点环
* - 最佳用户体验!
*/
示例 2: 交互式焦点测试工具
这个工具可以帮助你直观地理解不同输入方式下焦点状态的变化。
/* 测试元素样式 */
.test-element:focus {
outline: none; /* 移除默认焦点环 */
}
.test-element:focus-visible {
outline: 4px solid var(--primary);
outline-offset: 2px;
background: var(--primary-light);
}
/* JavaScript 检测焦点状态 */
element.addEventListener('focus', () => {
// 检查是否匹配 :focus-visible
const hasFocusVisible = element.matches(':focus-visible');
if (hasFocusVisible) {
console.log('键盘导航 - 显示焦点环');
} else {
console.log('鼠标点击 - 不显示焦点环');
}
});
示例 3: 不同元素的焦点可见性策略
不同类型的元素需要不同的焦点策略。按钮通常不需要在鼠标点击时显示焦点环, 但输入框和链接的焦点行为可能有所不同。
🔘 按钮 (Buttons)
策略:使用 :focus-visible,鼠标点击时不显示焦点环,键盘导航时显示。
这是最常见的使用场景。
🔗 链接 (Links)
策略:使用 :focus-visible,行为与按钮类似。
鼠标点击时不显示焦点环,键盘导航时显示。
📝 输入框 (Inputs)
策略:使用 :focus,无论鼠标还是键盘都显示焦点状态。
输入框是个例外,不应该使用 :focus-visible。
/* 按钮:使用 :focus-visible */
.demo-button:focus {
outline: none;
}
.demo-button:focus-visible {
outline: 3px solid var(--primary);
outline-offset: 3px;
}
/* 链接:使用 :focus-visible */
.demo-link:focus {
outline: none;
}
.demo-link:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 4px;
}
/* 输入框:使用 :focus(不用 :focus-visible) */
.demo-input:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
outline: none;
}
无障碍访问最佳实践
使用 :focus-visible 时,务必遵循无障碍访问的最佳实践, 确保所有用户都能获得良好的体验。
- 始终提供焦点样式 - 不要完全移除焦点指示器,只是智能地显示它
- 保持高对比度 - 焦点环应该在任何背景下都清晰可见(至少 3:1 对比度)
- 使用 outline 而非 border - outline 不影响布局,避免元素跳动
- 添加 outline-offset - 让焦点环与元素保持距离,更美观且更易识别
- 测试键盘导航 - 确保所有交互元素都可以通过 Tab 键访问
-
输入框例外 - 输入框应该始终显示焦点状态,使用
:focus而非:focus-visible
-
不要完全移除焦点样式 -
outline: none必须配合:focus-visible使用 - 不要使用低对比度颜色 - 浅灰色焦点环对视力障碍用户不友好
- 不要依赖颜色 - 除了颜色变化,还应该有其他视觉提示(如边框、阴影)
-
不要在所有元素上使用 :focus-visible - 输入框等需要持续显示焦点的元素应该使用
:focus
浏览器兼容性
:focus-visible 是一个相对较新的特性,但在现代浏览器中已经得到了广泛支持。
| 浏览器 | 版本支持 | 发布时间 |
|---|---|---|
| Chrome / Edge | ✓ 86+ | 2020年10月 |
| Firefox | ✓ 85+ | 2021年1月 |
| Safari | ✓ 15.4+ | 2022年3月 |
| iOS Safari | ✓ 15.4+ | 2022年3月 |
- 渐进增强 - 旧版浏览器会回退到
:focus行为,不影响基本功能 - Polyfill 可用 - 如需支持旧版浏览器,可以使用 focus-visible polyfill
- 特性检测 - 可以使用
@supports selector(:focus-visible)检测支持情况 - 现代项目推荐 - 如果不需要支持旧版浏览器,可以放心使用
- IE 浏览器完全不支持
:focus-visible - Safari 15.4 之前的版本不支持,但可以使用 polyfill
- 在不支持的浏览器中,
:focus-visible规则会被忽略 - 建议同时保留
:focus样式作为降级方案
总结
:focus-visible 是现代 Web 开发中非常重要的伪类选择器,
它让我们能够在保持良好无障碍访问的同时,提供更清爽的视觉体验。
- 浏览器根据输入方式智能判断是否显示焦点指示器
- 鼠标点击按钮时不显示焦点环,键盘导航时显示
- 输入框应该使用
:focus而非:focus-visible - 始终为
:focus-visible提供清晰的焦点样式 - 使用
outline而非border实现焦点指示器 - 配合
outline-offset让焦点环更美观
通过合理使用 :focus-visible,我们可以创造出既美观又易用的界面,
让鼠标用户和键盘用户都能获得最佳体验。这是现代 Web 无障碍访问的重要实践。
在下一个演示中,我们将学习 :nth-child() 的高级用法, 探索如何使用 An+B
语法实现复杂的元素选择模式。