键盘导航别再全屏扫 DOM 了,`focusgroup` 让浏览器自己管 Tab 顺序
键盘导航别再全屏扫 DOM 了,`focusgroup` 让浏览器自己管 Tab 顺序
导语
你项目里是不是也有一堆自定义下拉、弹窗、侧栏、轮播,每次做无障碍键盘导航都要写一堆 keydown、tabindex、焦点圈逻辑?我最近把这类交互统一收敛成一种思路:与其手动管焦点,不如让浏览器按“组件语义”自动排 Tab 顺序。focusgroup 就是这个思路里目前最值得提前落地的方案。
正文
常见场景其实很固定:侧栏打开后,焦点要进侧栏循环;弹窗出来,焦点要锁在对话框;轮播图里,左右按钮之间要能 Tab 但不跳出。
问题是这些逻辑大多散在各处:有的用 tabindex,有的用 focus(),有的在 keydown 里自己判断方向键。结果就是组件越复杂,键盘逻辑越容易漏,还经常和屏幕阅读器打架。
现在浏览器给了一个更接近语义的解法:用 focusgroup 把一组元素标记成同一组。组内的 Tab 只在组内循环,组外的默认行为不变。
好处是它把“谁和谁是一组”从 JS 逻辑里抽出来,变成 HTML 属性表达,比散落在各处的 keydown 更容易维护,也更容易被辅助技术理解。
<!-- 侧栏:Tab 只在按钮组里循环 -->
<div role="dialog" aria-modal="true" aria-label="设置">
<div focusgroup>
<button>个人资料</button>
<button>通知设置</button>
<button>隐私设置</button>
<button>关闭</button>
</div>
</div>
<!-- 轮播:左右按钮成组,不跳到页面其它按钮 -->
<div class="carousel" focusgroup>
<button aria-label="上一张">←</button>
<button aria-label="下一张">→</button>
</div>
<!-- 工具栏:一组工具键 -->
<div role="toolbar" focusgroup>
<button>加粗</button>
<button>斜体</button>
<button>链接</button>
</div>
如果你用的是 React,也可以封装成更接近组件的写法。
function FocusGroup({ children, role }) {
return (
<div {...(role ? { role } : {})} focusgroup>
{children}
</div>
);
}
// 使用
<FocusGroup role="toolbar">
<button>加粗</button>
<button>斜体</button>
<button>链接</button>
</FocusGroup>
我现在的判断标准很简单:如果一个组件的键盘交互仍然靠大量 keydown 手动计算下一个元素,那它大概率该考虑收拢成 focusgroup;如果只是普通页面内容流,那就继续用默认 Tab 顺序。
这个属性真正的好处是:可访问性逻辑开始和业务逻辑分离,以后换组件库、换交互形态,焦点行为不用跟着重写。
收尾
这周你可以先挑一个最复杂的组件试:比如自定义下拉或轮播。把原来的 keydown 焦点计算替换成 focusgroup,看能不能把代码减掉一半。要是跑通了,你会发现很多以前靠 tabindex 和 focus() 拼出来的东西,其实本来就不该那么写。
评论区
0 条评论
登录后可评论。













