Table keyboard navigation: scrollIntoViewport containingElement centering causes vertical viewport jumps in bounded scroll containers
- Dominant language
- TypeScript
- Stars
- 15.9k
- Forks
- 1.6k
- Avg merge
- 3d 9m
- Merged PRs (30d)
- 59
Description
### Provide a general summary of the issue here
When keyboard-navigating a React Aria `Table` inside a **bounded scroll container** (explicit `height`/`maxHeight`) with **sticky header/column** and **`scroll-padding`** on the scroll container, `scrollIntoViewport` can cause sudden **vertical viewport jumps** even though focus remains on the correct cell.
This is especially visible when:
- Moving **horizontally** along a row (ArrowLeft/ArrowRight) — `scrollTop` changes unexpectedly
- Moving **vertically** at the edges (e.g. ArrowUp from the first body row to the column header, ArrowDown near the bottom) — viewport recenters to the middle of the table instead of scrolling one row
Stock RAC Storybook stories without `scroll-padding` + sticky + bounded vertical scroll do not reproduce the issue.
https://github.com/user-attachments/assets/c7541004-8823-42d3-b68a-cf3c2c86d55f
### 🤔 Expected Behavior?
Keyboard navigation should scroll the bounded container just enough to keep the focused cell visible (respecting `scroll-padding`), without recentering the entire `` in the viewport.
### 😯 Current Behavior
`useSelectableCollection` calls `scrollIntoView(scrollContainer, element)` (padding-aware), then `scrollIntoViewport(element, { containingElement: table })`.
In `scrollIntoViewport` (`@react-aria/utils` / `react-aria` `scrollIntoView.ts`), after `targetElement.scrollIntoView({ block: 'nearest' })`, if the cell's bounding rect moved by >1px in **either** axis, the fallback runs:
```ts
containingElement?.scrollIntoView?.({ block: 'center', inline: 'center' });
targetElement.scrollIntoView?.({ block: 'nearest' });
```
Horizontal keyboard moves change left, which trips this fallback and calls table.scrollIntoView({ block: 'center', ... }), causing unwanted vertical scroll. Vertical edge navigation has the same problem when top changes.
The padding-aware scrollIntoView on the scroll container already positions the cell correctly when scroll-padding accounts for sticky regions.
Repro in StackBlitz: https://stackblitz.com/edit/github-budc6mta-fdxhpe8x?file=src%2Findex.css
### 💁 Possible Solution
`scrollIntoViewport` runs a padding-aware scroll on scroll parents, then a native `targetElement.scrollIntoView({ block: 'nearest' })`, then — if position changed by >1px in **either** axis — calls `containingElement.scrollIntoView({block: 'center', inline: 'center' })`. That last step recenters the entire table and causes vertical viewport jumps during horizontal keyboard navigation.
**Possible fix:**
1. Skip `containingElement` centering when the padding-aware scroll parent pass
already satisfied visibility (especially with `scroll-padding` for sticky UI).
2. If a containing-element fallback is still needed, only trigger it when
**vertical** position remains unsatisfactory (`originalTop` vs `newTop`), not
when only `left` changed.
**Optional:** expose `centerContainingElement?: boolean` (default `false`) for consumers who need the legacy behavior.
Related: #8977 (same fallback mechanism, different scroll context).
### 🔦 Context
We hit this building a Table with sticky header/column and scroll-padding on ResizableTableContainer to keep keyboard focus clear of pinned regions. We worked around it with a yarn patch on react-aria@3.48.0 that removes the containing-element centering fallback.
RAC version: 1.17.0 / react-aria 3.48.0
### 🖥️ Steps to Reproduce
Render a Table inside ResizableTableContainer with bounded height (e.g. maxHeight: 400px) and overflow: auto
Enable sticky header and/or sticky column
Set scroll-padding-block-start / scroll-padding-inline-start on the scroll container for sticky clearance
Keyboard-focus cells and move horizontally along a row, or ArrowUp/ArrowDown at the top/bottom of the visible area
Observe scrollTop jumping / viewport recentering while focus stays correct
### Version
react-aria-components@1.17.0 (react-aria@3.48.0)
### What browsers are you seeing the problem on?
Chrome, Safari, Firefox, Microsoft Edge
### If other, please specify.
_No response_
### What operating system are you using?
masOS
### 🧢 Your Company/Team
MaintainX
### 🕷 Tracking Issue
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.