Skip to content

fix(app-router): respect scroll padding top as viewport boundary during navigation - #2839

Open
NriotHrreion wants to merge 1 commit into
cloudflare:mainfrom
NriotHrreion:fix/issue-2810-scroll-padding-top-boundary
Open

fix(app-router): respect scroll padding top as viewport boundary during navigation#2839
NriotHrreion wants to merge 1 commit into
cloudflare:mainfrom
NriotHrreion:fix/issue-2810-scroll-padding-top-boundary

Conversation

@NriotHrreion

@NriotHrreion NriotHrreion commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Closes #2810. Ports vercel/next.js#96308 (vercel/next.js@da90782)

Overview

Align App Router navigation scrolling with Next.js when applications reserve space for sticky headers using root-level scroll-padding-top.

This ensures navigation targets that are visually obscured within the reserved top offset are treated as outside the usable viewport, while targets already visible below that boundary retain the current scroll position.

What changed

Added a function getScrollPaddingTopPx() ported from Next.js.

function getScrollPaddingTopPx(element: HTMLElement, viewportHeight: number): number {
  const scrollPaddingTop = getComputedStyle(element).scrollPaddingTop;
  const value = Number.parseFloat(scrollPaddingTop);
  if (!Number.isFinite(value) || value < 0) return 0;
  if (scrollPaddingTop.endsWith("px")) return value;
  if (scrollPaddingTop.endsWith("%")) return (value / 100) * viewportHeight;
  return 0;
}

And this function is lazily called inside topOfElementInViewport() to ensure getComputedStyle() is called after checking rect !== null. (And this is also how Next.js does)

Verification

  • playwright test --project=app-router tests/e2e/app-router/nextjs-compat/router-autoscroll.spec.ts

This fix has been verified in my local repro project.

@pkg-pr-new

pkg-pr-new Bot commented Aug 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vinext/cloudflare@2839
npm i https://pkg.pr.new/create-vinext-app@2839
npm i https://pkg.pr.new/@vinext/types@2839
npm i https://pkg.pr.new/vinext@2839

commit: be254b9

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared be254b9 against base 07cf9e5 using alternating same-runner rounds. Next.js was unchanged and skipped.

1 improved · 0 regressed · 5 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 134.7 KB 134.7 KB ⚫ +0.1%
Client entry size (gzip) vinext 122.2 KB 122.3 KB ⚫ +0.1%
Dev server cold start vinext 2.94 s 2.87 s 🟢 -2.4%
Production build time vinext 3.16 s 3.16 s ⚫ -0.2%
RSC entry closure size (gzip) vinext 113.9 KB 113.8 KB ⚫ -0.0%
Server bundle size (gzip) vinext 191.4 KB 191.5 KB ⚫ +0.0%

View detailed results and traces

🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head

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.

App Router navigation scroll: respect root scroll-padding-top as viewport boundary (don't skip scroll when target is under sticky header)

1 participant