diff --git a/packages/next/client/components/layout-router.client.tsx b/packages/next/client/components/layout-router.client.tsx index 5dfa3fb80fd4b58..fdd0d689ede4e56 100644 --- a/packages/next/client/components/layout-router.client.tsx +++ b/packages/next/client/components/layout-router.client.tsx @@ -164,7 +164,11 @@ export function InnerLayoutRouter({ focusAndScrollElementRef.current.focus() // Only scroll into viewport when the layout is not visible currently. if (!topOfElementInViewport(focusAndScrollElementRef.current)) { + const htmlElement = document.documentElement + const existing = htmlElement.style.scrollBehavior + htmlElement.style.scrollBehavior = 'auto' focusAndScrollElementRef.current.scrollIntoView() + htmlElement.style.scrollBehavior = existing } } }, [focusAndScrollRef]) diff --git a/packages/next/client/index.tsx b/packages/next/client/index.tsx index 7324cccd7d90849..c0f5d8be0337347 100644 --- a/packages/next/client/index.tsx +++ b/packages/next/client/index.tsx @@ -688,7 +688,11 @@ function doRender(input: RenderRouteInfo): Promise { } if (input.scroll) { + const htmlElement = document.documentElement + const existing = htmlElement.style.scrollBehavior + htmlElement.style.scrollBehavior = 'auto' window.scrollTo(input.scroll.x, input.scroll.y) + htmlElement.style.scrollBehavior = existing } } diff --git a/packages/next/shared/lib/router/router.ts b/packages/next/shared/lib/router/router.ts index cda9125962a0719..c0e6bd190168d03 100644 --- a/packages/next/shared/lib/router/router.ts +++ b/packages/next/shared/lib/router/router.ts @@ -655,6 +655,14 @@ interface FetchNextDataParams { unstable_skipClientCache?: boolean } +function handleSmoothScroll(fn: () => void) { + const htmlElement = document.documentElement + const existing = htmlElement.style.scrollBehavior + htmlElement.style.scrollBehavior = 'auto' + fn() + htmlElement.style.scrollBehavior = existing +} + function tryToParseAsJSON(text: string) { try { return JSON.parse(text) @@ -2141,7 +2149,7 @@ export default class Router implements BaseRouter { // Scroll to top if the hash is just `#` with no value or `#top` // To mirror browsers if (hash === '' || hash === 'top') { - window.scrollTo(0, 0) + handleSmoothScroll(() => window.scrollTo(0, 0)) return } @@ -2150,14 +2158,14 @@ export default class Router implements BaseRouter { // First we check if the element by id is found const idEl = document.getElementById(rawHash) if (idEl) { - idEl.scrollIntoView() + handleSmoothScroll(() => idEl.scrollIntoView()) return } // If there's no element with the id, we check the `name` property // To mirror browsers const nameEl = document.getElementsByName(rawHash)[0] if (nameEl) { - nameEl.scrollIntoView() + handleSmoothScroll(() => nameEl.scrollIntoView()) } }