弹窗打开后需立即将焦点设在首个可聚焦元素上,关闭时须恢复原焦点;:focus-visible更优但需兼容处理,避免outline被重置或DOM未就绪导致失焦。

弹窗打开后如何让首个可聚焦元素自动获得焦点
弹窗(modal)不自动聚焦,会导致键盘用户无法用 Tab 导航、屏幕阅读器无法定位起点,也意味着高亮边框(:focus-visible 或 :focus 样式)不会出现。关键不是“加边框”,而是让浏览器知道该聚焦谁。
- 弹窗容器本身(如 )默认不可聚焦,需手动添加
tabindex="-1"- 打开弹窗后,立即调用
.focus()到第一个逻辑可操作元素(通常是确认按钮或输入框)- 避免聚焦到
或无交互语义的容器上——它可能触发:focus但无实际用途,且干扰辅助技术const modal = document.getElementById('my-modal'); const firstFocusable = modal.querySelector('button, input, select, textarea, [tabindex]:not([tabindex="-1"])'); modal.showModal(); // 或通过 class 控制显隐 if (firstFocusable) { firstFocusable.focus(); }为什么
:focus边框没显示?检查这三件事CSS 的
:focus不生效,大概率不是样式写错,而是聚焦行为根本没发生,或被浏览器/框架抑制。-
outline: none被全局重置(尤其在 CSS Reset 或 UI 框架中),必须显式恢复:button:focus { outline: 2px solid #007bff; outline-offset: 2px; } - 使用了
outline: 0或outline: transparent—— 这些等同于移除焦点指示,不符合无障碍要求 - 弹窗内容是动态渲染(如 React/Vue 组件),
.focus()被调用时 DOM 尚未挂载,需确保在渲染完成后再执行(如setTimeout(() => el.focus(), 0)或框架对应的生命周期钩子)
:focus-visible和:focus怎么选?:focus-visible是更现代、更友好的选择:它只在用户**明确用键盘触发聚焦**(如 Tab)时生效,鼠标点击后不会显示边框,体验更自然。- 旧版浏览器(如 Safari :focus-visible,需回退到
:focus - 不要同时写
button:focus, button:focus-visible—— 会覆盖掉:focus-visible的智能判断,直接用button:focus-visible即可 - 若需兼容老浏览器,可用
@supports selector(:focus-visible)做渐进增强
button:focus-visible { outline: 2px solid #007bff; outline-offset: 2px; } @supports not selector(:focus-visible) { button:focus { outline: 2px solid #007bff; outline-offset: 2px; } }弹窗关闭后必须手动恢复原焦点
关闭弹窗时不把焦点还给触发它的元素(比如一个
button),会导致键盘用户迷失上下文,下一次按 Tab 可能跳到页面顶部或不可预期位置。立即学习“前端免费学习笔记(深入)”;
- 打开弹窗前,用
document.activeElement记录当前聚焦元素 - 关闭弹窗后,检查该元素是否仍存在于 DOM 且可聚焦,再调用
.focus() - 避免聚焦到已销毁或
display: none的元素上,否则焦点会落到body,引发滚动或不可见聚焦环
这个步骤容易被忽略,但恰恰是 WCAG 2.4.3(Focus Order)和 2.4.7(Focus Visible)合规的关键一环。
- 打开弹窗后,立即调用










