Keep Keyboard Focus Stable When a Virtualized Grid Recycles Its Rows

작성자

카테고리:

← 피드로
DEV Community · babycat · 2026-07-19 개발(SW)

babycat

A keyboard user focuses row 40, column 3. Scrolling recycles that DOM node. Focus falls to <body>, while a screen reader announces the wrong row after sorting. Virtualization saved nodes but broke navigation.

Separate logical and DOM focus

type ActiveCell={rowId:string,columnId:string};
let active:ActiveCell={rowId:'row-0040',columnId:'status'};

Enter fullscreen mode Exit fullscreen mode

Store stable row IDs, not rendered indexes. When the active row leaves the window, keep logical focus and move DOM focus to a grid proxy or newly rendered equivalent. After sorting, locate the same row ID at its new position.

<div role="grid" aria-rowcount="10000" tabindex="0" aria-activedescendant="cell-row-0040-status"></div>

Enter fullscreen mode Exit fullscreen mode

Event Expected focus evidence ArrowDown next logical row announced scroll recycles active row focus remains in grid sort same row ID stays active filter removes row deterministic fallback announced loading error retry reachable without pointer

Build Playwright tests for document.activeElement, aria-activedescendant, and row/column attributes. Add manual checks with keyboard, zoom, and at least one browser/screen-reader pair. Automated assertions cannot validate announcement quality alone.

Test cancellation and retry during async page loading; never announce every scroll frame. This pattern covers one virtualization strategy, not all grid libraries. When the active item disappears after filtering, should your product focus the nearest row, the grid heading, or the filter control?

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다