matterlabo docs
09 前端畫面與架構

09 重新整理後停留在舊 scroll 位置

Reload 後頁面自動停在上次的 scroll 位置,而不是從這次初始化流程的起點開始。

30 秒摘要

  • 現象:reload 後頁面自動停在上次的 scroll 位置,而不是從這次初始化流程的起點開始。 developer.mozilla
  • 影響:首屏動畫、ScrollTrigger、pin、鎖滾動流程可能從錯誤起點初始化。
  • 優先方向:先檢查是否在 hydration 前設定、是否為 Pages Router、是否放在 pages/_documentnextjs

先做這三步

  1. 手動捲到中後段後重新整理,確認能否穩定重現。
  2. 檢查專案是否有 pages/_document.tsx / pages/_document.jsx;Next.js 規定 custom Document 需包含 <Html>、<Main />、<NextScript /> 等必要結構。 nextjs
  3. 確認 history.scrollRestoration = "manual" 是否早於 React hydration 執行;beforeInteractive 類型的腳本時機屬於 hydration 前。 nextjs

標準解法

pages/_document<body> 最前面加入最小 inline script,將 history.scrollRestoration 設為 manual。MDN 說明 manual 代表頁面位置不會被自動恢復。 developer.mozilla

範例:

import { Html, Main, NextScript } from "next/document";

export default function Document() {
  return (
    <Html data-font-smoothing="figma">
      <body className="relative">
        {/* Prevent browser scroll restoration before React hydration */}
        <script
          dangerouslySetInnerHTML={{
            __html: `
              if ("scrollRestoration" in history) {
                history.scrollRestoration = "manual";
              }
            `,
          }}
        />
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

預期結果:reload 後不再沿用舊 scroll 位置,首屏動畫與 ScrollTrigger 從一致起點初始化。 developer.mozilla

驗證方式

  • 捲到中後段後重新整理,確認頁面不會停在舊位置。 developer.mozilla
  • 確認首屏動畫、解鎖流程與 ScrollTrigger 狀態正常。

升級條件

  • 已設定 manual 仍無效。
  • 問題其實來自自訂滾動容器、第三方 smooth scroll、或 GSAP 初始化順序。

備註

這類問題通常是瀏覽器自動恢復舊 scroll 位置,導致動畫頁初始化起點不一致;MDN 對 scrollRestoration 的定義可作為判斷基礎。建議先檢查 pages/_document 與 hydration 前時機,再套用上面的做法。 nextjs

On this page