如何在溢出容器中通过tabindex确定键盘Tab切换的当前焦点项
实现当前Tab聚焦元素识别的方向
核心实现逻辑
- 不需要手动追踪Tab键的切换顺序,利用DOM原生的焦点触发机制即可完成位置识别:可聚焦元素(带
tabindex)获得焦点时,浏览器会自动触发focus事件,失去焦点时触发blur事件,全程不需要额外拦截Tab键的默认行为 - 因为当前条目是通过Angular
*ngFor循环渲染的,直接在模板上给每个条目绑定对应事件,把循环索引传入回调,就能直接拿到当前聚焦条目的位置
对应的模板改造代码:
<div class="container"> <ul class="content"> <li *ngFor="let item of items; let i = index" tabindex="0" class="item" (focus)="recordFocusPosition(i)" (blur)="clearFocusPosition(i)" ></li> </ul> </div>
对应的组件类逻辑:
// 全局维护当前焦点的索引位置,需要获取用户操作位置时直接读取这个值即可 activeFocusIndex: number | null = null; /** 条目获得焦点时记录位置 */ recordFocusPosition(index: number) { this.activeFocusIndex = index; // 可叠加溢出容器的联动逻辑:当前聚焦条目如果在可视区外,自动调用scrollIntoView对齐到容器可视区域 } /** 条目失去焦点时清除记录的位置 */ clearFocusPosition(index: number) { if (this.activeFocusIndex === index) { this.activeFocusIndex = null; } }
优化建议
- 搭配
:focus-visible伪类写聚焦样式:浏览器会自动区分是鼠标点击触发的聚焦,还是键盘Tab操作触发的聚焦,刚好匹配当前的Tab切换场景,不会出现鼠标点击后也显示生硬聚焦边框的问题,示例样式:.item:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; } - 不需要主动遍历DOM检查
document.activeElement判断当前聚焦项位置,通过事件回调维护的索引值是同步更新的,性能更好 - 现有Tab循环逻辑不需要改动,和位置识别的逻辑完全独立:如果后续需要调整循环规则,只需要在第一个条目反向Tab、最后一个条目正向Tab的场景,拦截对应元素的
keydown.tab事件,手动把焦点转移到循环目标位置即可
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

