无障碍访问咨询:汉堡菜单Tab键循环聚焦的非JS实现方案
关于抽屉菜单Tab焦点循环的实现方案
目前没有纯HTML/CSS的非JavaScript方案实现这种局部焦点循环,业内普遍都是用JavaScript来处理这个需求。
为什么非JS方案不可行?
原生Tab键的默认行为是遍历整个页面内所有可聚焦元素(包括链接、按钮、表单控件等),它不会识别“抽屉菜单”这个局部区域的边界。所以默认情况下,当焦点移动到菜单的最后一个元素后,再按Tab会直接跳转到页面其他区域的可聚焦元素,而非菜单的第一个元素。
主流的JavaScript实现思路
核心逻辑是监听菜单内的键盘事件,拦截Tab键的默认行为,手动控制焦点的循环:
- 获取菜单内所有可聚焦元素(比如
<a>、<button>等) - 监听
keydown事件,判断当前焦点所在元素和按键组合:- 若在最后一个元素按下
Tab(未按住Shift),阻止默认行为,将焦点移到第一个元素 - 若在第一个元素按下
Shift+Tab,阻止默认行为,将焦点移到最后一个元素
- 若在最后一个元素按下
简单实现示例
// 获取菜单元素及内部可聚焦项 const drawerMenu = document.getElementById('drawer-menu'); const focusableItems = drawerMenu.querySelectorAll('a, button, input'); const firstItem = focusableItems[0]; const lastItem = focusableItems[focusableItems.length - 1]; // 监听键盘事件 drawerMenu.addEventListener('keydown', (e) => { if (e.key !== 'Tab') return; // 最后一项按Tab,跳转到第一项 if (!e.shiftKey && document.activeElement === lastItem) { e.preventDefault(); firstItem.focus(); } // 第一项按Shift+Tab,跳转到最后一项 else if (e.shiftKey && document.activeElement === firstItem) { e.preventDefault(); lastItem.focus(); } });
额外的无障碍提示
- 菜单弹出时,建议主动将焦点移到菜单内的第一个元素(或菜单容器),避免用户需要多次Tab才能进入菜单
- 菜单关闭时,将焦点放回触发菜单的汉堡按钮,保证操作的连贯性
- 可以给菜单添加
aria-modal="true"属性,并配合inert属性让页面其他区域暂时不可聚焦(部分浏览器可能需要JS辅助实现inert的兼容)
内容的提问来源于stack exchange,提问作者Kalarm
相关产品推荐
相关产品推荐

