Skip to content

fix: floor fractional layout widths to prevent horizontal scrollbar in Virtualizer - #10483

Open
waterWang wants to merge 1 commit into
adobe:mainfrom
waterWang:fix/virtualizer-width-rounding
Open

fix: floor fractional layout widths to prevent horizontal scrollbar in Virtualizer#10483
waterWang wants to merge 1 commit into
adobe:mainfrom
waterWang:fix/virtualizer-width-rounding

Conversation

@waterWang

Copy link
Copy Markdown

What was changed

When a Virtualizer container has a fractional width (e.g. 250.5px — easily produced by two 50%-width lists side by side), the browser reports an integer clientWidth that can be rounded up. The layouts then set contentSize.width (and item rect widths) to that larger value, so the content element is wider than the container's real CSS box — producing a horizontal scrollbar.

Why it happened

ScrollView only applies overflow-x: hidden when contentSize.width === state.size.width (the integer clientWidth). When the layout reports a width that was rounded up past the actual CSS width, that equality fails and overflow: auto kicks in.

How it's fixed

Floor the width (round down) in the layouts, matching the container's sub-pixel CSS width, so the equality holds and nothing overflows:

  • ListLayout: floor contentSize.width/height plus buildSection, buildSectionHeader, and buildItem rect widths
  • GridLayout: floor contentSize.width
  • WaterfallLayout: floor contentSize.width
  • @react-spectrum/ai ListLayout: floor contentSize.width

This mirrors the previously merged Table fix (#9448 / PR #10238) which floors availableWidth in TableUtils.calculateColumnSizes.

Tests

Added ListLayout.test.ts verifying:

  1. contentSize.width is floored when the viewport width is fractional (250.5 → 250)
  2. Integer viewport widths are unchanged
  3. Item rect widths do not exceed the floored width

Closes #10471

…al scrollbar from fractional container widths

When the container width is fractional (e.g. 250.5px), the browser's
clientWidth returns an integer that may be rounded up, causing the
virtualizer's contentSize.width to be larger than the actual available
space. This produces a horizontal scrollbar.

Fix: floor the width in contentSize calculation and item rect width
computation across ListLayout, GridLayout, WaterfallLayout, and the
AI ListLayout, ensuring no layout spills beyond the container.

Reference: TableLayout fix adobe#9448 (PR adobe#10238) which used the same
Math.floor approach in TableUtils.calculateColumnSizes.

Fixes adobe#10471
@github-actions github-actions Bot added the AI label Aug 20, 2026
@snowystinger

Copy link
Copy Markdown
Member

Looks like lint is failing and the CLA maybe hasn't been signed with the e-mail that created this PR. https://github.com/adobe/react-spectrum/blob/main/CONTRIBUTING.md#contributor-license-agreement

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Virtualizer rounding of width causes a horizontal scrollbar

2 participants