Skip to content

fix(virtualizer): preserve subpixel precision in ScrollView to preven… - #10489

Open
devo-id wants to merge 5 commits into
adobe:mainfrom
devo-id:fix/virtualizer-fractional-width
Open

fix(virtualizer): preserve subpixel precision in ScrollView to preven…#10489
devo-id wants to merge 5 commits into
adobe:mainfrom
devo-id:fix/virtualizer-fractional-width

Conversation

@devo-id

@devo-id devo-id commented Aug 20, 2026

Copy link
Copy Markdown

What was changed

When a Virtualizer container has a fractional layout width (e.g. 250.5px, common when two components sit side-by-side in a 50% flex layout), the browser's integer dom.clientWidth rounds up to 251px per the CSSOM View spec. ScrollView was passing this rounded integer to the layout engine, which sized the content wrapper to 251px inside a 250.5px container — producing an unwanted horizontal scrollbar.

Why it happened

ScrollView.tsx read container dimensions via dom.clientWidth / dom.clientHeight, which are always integers in the browser. The Virtualizer's layout engine then sized the content element to those rounded values, causing a 0.5px overflow that triggered overflow: auto to show a scrollbar.

How it's fixed

Introduced getClientSize(dom) in ScrollView.tsx that derives exact subpixel dimensions from getBoundingClientRect() while correctly subtracting borders and scrollbars (dom.offsetWidth - dom.clientWidth). This gives the layout engine the true floating-point scrollport dimensions.

Fixing at the measurement source means all layouts (ListLayout, GridLayout, WaterfallLayout, custom layouts) automatically benefit — no per-layout patching needed.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices
  • I understand every change in this PR and can explain why it's there.
  • If AI-assisted, I followed our AI contribution guidance and pointed my assistant at CLAUDE.md.

📝 Test Instructions:

  1. Run yarn jest packages/react-aria-components/test/ListBox.test.js -t "fractional container" — both tests should pass.
  2. Render a virtualized ListBox inside a 501px container split into two 50% columns (so each column is 250.5px). Confirm no horizontal scrollbar appears.

Closes #10471

@devo-id devo-id closed this Aug 20, 2026
@devo-id devo-id reopened this Aug 20, 2026
@devo-id
devo-id force-pushed the fix/virtualizer-fractional-width branch from cab6ae5 to 62225e1 Compare August 20, 2026 19:35
@devo-id
devo-id marked this pull request as draft August 20, 2026 19:45

@snowystinger snowystinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a better approach than the already existing PR. While the unit test is kind of useful, it'd be more useful to have a storybook setup with the 50% widths you mention, then we can put it in a chromatic story and get visual regression testing that actually uses the browser instead of mocking everything in jsdom. Would you mind putting that together?

Is there a reason you have left it as a draft?

Thank you!

@devo-id
devo-id force-pushed the fix/virtualizer-fractional-width branch from 62225e1 to 22f0f72 Compare August 21, 2026 05:26
@devo-id devo-id closed this Aug 21, 2026
@devo-id devo-id reopened this Aug 21, 2026
@devo-id
devo-id marked this pull request as ready for review August 21, 2026 05:28
@devo-id

devo-id commented Aug 21, 2026

Copy link
Copy Markdown
Author

Hi @snowystinger,

Thanks for taking a look and for the feedback!

About the draft status: I temporarily moved it to draft while looking into a CircleCI failure in ListViewDnd.test.js. In jsdom, drag-and-drop mocks were returning item coordinates that getClientSize was picking up, which shrunk the mock container height in that test. I’ve refined the test environment handling in ScrollView.tsx, and all test suites are passing cleanly now.

Storybook / Chromatic: I've added a FractionalWidth story to packages/react-aria-components/stories/ListBox.stories.tsx that renders two side-by-side virtualized ListBoxes at 50% width inside a 501px container (giving 250.5px per list).

I've marked the PR as ready for review.

Thanks!

@devo-id devo-id closed this Aug 23, 2026
@devo-id devo-id reopened this Aug 23, 2026
@devo-id

devo-id commented Aug 23, 2026

Copy link
Copy Markdown
Author

recheck

@devo-id

devo-id commented Aug 23, 2026

Copy link
Copy Markdown
Author

I’ve submitted and verified the Adobe CLA and received the signed agreement by email.

I also closed and reopened the PR as requested and tried the suggested recheck, but the CLA check is still showing “No signed agreements were found.”

I’ve contacted the Adobe Open Source Office by email to have the CLA association checked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Virtualizer rounding of width causes a horizontal scrollbar

2 participants