弹窗内可聚焦<li>标签tabindex循环失效问题求助
问题分析与修复方案
核心问题
焦点循环二次失效的根源是页面存在多层可聚焦元素:li标签设置了tabindex="1",内部的.filter-item__chip又设置了tabindex="0",导致Tab遍历的焦点链混乱。首次循环是浏览器默认的焦点溢出跳转,二次遍历后焦点追踪机制出现异常。
修复步骤
1. 清理冗余tabindex,统一焦点入口
移除多层可聚焦元素的tabindex,只保留li的可聚焦属性,避免焦点分散:
<!-- 修改后的HTML结构 --> <ul class="filter-group__list filter-group__list--chips" tabindex="0" data-layout="3col"> <li class="filter-item filter-item--chip" tabindex="0"> <label data-filter-item="" class="filter-item__content " for="filter--filter.v.option.size--XS--top-bar"> <input type="checkbox" name="filter.v.option.size" value="XS" class="filter-item__checkbox visually-hidden" data-filter-item-input="" tabindex="-1" data-filter="filter.v.option.size=XS" data-value-escaped="XS" id="filter--filter.v.option.size--XS--top-bar"> <div class="filter-item__content-inner"> <div class="filter-item__chip">XS</div> </div> </label> </li> <!-- 其余li标签同理移除内部.filter-item__chip的tabindex="0",保留li的tabindex="0" --> </ul>
2. 实现受控的焦点循环逻辑
通过JavaScript监听Tab键事件,手动控制焦点跳转,确保循环稳定生效:
const filterList = document.querySelector('.filter-group__list--chips'); const filterItems = Array.from(filterList.querySelectorAll('.filter-item')); // 监听Tab键的正向/反向遍历 filterList.addEventListener('keydown', (e) => { if (e.key === 'Tab') { const currentItem = document.activeElement.closest('.filter-item'); const currentIndex = filterItems.indexOf(currentItem); // 正向遍历:最后一个跳转到第一个 if (!e.shiftKey && currentIndex === filterItems.length - 1) { e.preventDefault(); filterItems[0].focus(); } // 反向遍历:第一个跳转到最后一个 else if (e.shiftKey && currentIndex === 0) { e.preventDefault(); filterItems[filterItems.length - 1].focus(); } } }); // 给li添加回车/空格选中逻辑(符合无障碍交互规范) filterItems.forEach(item => { item.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); const checkbox = item.querySelector('.filter-item__checkbox'); checkbox.checked = !checkbox.checked; // 可在此添加选中状态的视觉反馈 } }); });
3. 无障碍语义优化(可选)
给容器和列表项添加ARIA角色,提升屏幕阅读器兼容性:
<ul class="filter-group__list filter-group__list--chips" tabindex="0" data-layout="3col" role="menu"> <li class="filter-item filter-item--chip" tabindex="0" role="menuitem"> <!-- 内容 --> </li> </ul>
验证标准
- 点击ul容器获取焦点,按Tab键遍历所有li,确认每次到达最后一项后都能跳回第一项。
- 按住Shift+Tab反向遍历,确认第一项能跳回最后一项。
- 重复多次循环,焦点跳转逻辑保持稳定。
内容的提问来源于stack exchange,提问作者avocado
相关产品推荐
相关产品推荐

