next.js
da907823 - Fix App Router scroll padding visibility (#96308)

Commit
42 days ago
Fix App Router scroll padding visibility (#96308) ## Summary - Treat the root `scroll-padding-top` as the lower boundary of the usable viewport during App Router navigations, so content obscured by a sticky header is not incorrectly considered visible. - Preserve the merged Fragment scroll-ownership state machine: empty Fragments remain unavailable targets, while real targets are classified against the padding-aware viewport. - Resolve pixel and percentage values and use the same visibility rule in both the legacy element handler and the Fragment-ref handler. - Add regression coverage showing that Next scrolls when the destination is hidden inside the padding boundary, while preserving the current scroll position when the destination is genuinely visible below it. ## Performance The root computed style is resolved lazily, only after the candidate produces client rects. Empty Fragments and hash navigations do not perform this lookup. For a real route-scroll target, the resolved value is cached locally and reused by the second geometry check after `scrollTop = 0`. This does not add work to scroll events or every render, and keeping the value local allows responsive CSS, root classes, and custom properties to change between navigations. In a 50-iteration dirty-style Chromium probe, both the existing and updated paths reported 50 style recalculations and 50 layouts, indicating that the lookup reused the style/layout update already required by the handler in that test. ## Related work #96342 is now merged into `canary` and handles empty Fragment scroll ownership. This PR composes with its `NoClientRects` / `InViewport` / `OutOfViewport` state machine by changing only the visible-region boundary for real targets. ## Verification - `HEADLESS=true pnpm test-dev-turbo test/e2e/app-dir/router-autoscroll/router-autoscroll.test.ts -t "scroll padding"` (3/3) - `HEADLESS=true __NEXT_EXPERIMENTAL_APP_NEW_SCROLL_HANDLER=false pnpm test-dev-turbo test/e2e/app-dir/router-autoscroll/router-autoscroll.test.ts -t "scroll padding"` (3/3) - `HEADLESS=true pnpm test-dev-turbo test/e2e/app-dir/parallel-routes-scroll-owner/parallel-routes-scroll-owner.test.ts` (8/8) - `HEADLESS=true pnpm test-dev-webpack test/e2e/app-dir/parallel-routes-scroll-owner/parallel-routes-scroll-owner.test.ts` (8/8) - `HEADLESS=true pnpm test-dev-turbo test/e2e/app-dir/navigation-focus/navigation-focus.test.ts` (5/5) - Manually compared the same sticky-header reproduction before and after the change. <!-- NEXT_JS_LLM -->
Author
Parents
Loading