什麼 SPA 頁面要用 overflow: hidden 打造「外層不滾動」結構? - daniel-qa/Vue GitHub Wiki

  • 背景:SPA 是「單頁應用」(Single Page Application)

SPA 不會像傳統網站那樣切換頁面,而是透過前端框架(如 Vue、React)動態切換內容區塊。

範例代碼 (概念說明)

<template>
  <div class="app-container">
    <header class="header">這是 Header(固定不動)</header>

    <div class="main">
      <aside class="sidebar">這是 Sidebar(固定不動)</aside>

      <div class="content">
        <div class="scroll-area">
          <!-- 模擬很多內容 -->
          <p v-for="i in 100" :key="i">這是第 {{ i }} 行內容</p>
        </div>
      </div>
    </div>
  </div>
</template>
/* 外層容器:固定高度 & 不滾動 */
.app-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden; /* ✨關鍵:鎖住外層滾動 */
}

/* Content 是主要內容區 */
.content {
  flex: 1;
  background: #fafafa;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ✨ 真正可滾動的區塊 */
.scroll-area {
  flex: 1;
  overflow-y: auto; /* ✅ 只讓這裡滾動 */
  padding: 20px;
}

這種設計有一個核心目標:

👉 主框架不動、內容切換流暢、狀態不重置。

🧱 為什麼「外層不滾動」能讓結構更穩定?

  1. 🪄 保持主框架穩定(Header / Sidebar 不會跳動)

如果整個

都可以滾動,當內容切換時:

捲軸長度可能改變,導致頁面「跳一下」。

固定在上方的 header、側邊選單位置可能跟著晃動。

用 overflow: hidden; 固定外層高度後,主框架就變成「穩如山」:

<App> ← 不會滾動
 ├─ <Header> ← 固定
 ├─ <Sidebar> ← 固定
 └─ <RouterView> ← 捲動在這裡
  1. 📏 控制滾動行為更精準(誰滾動你說了算)

如果讓整個

滾動,會產生以下問題:

元件之間爭奪滾動權(像對話框、Drawer、下拉選單等會受干擾)。

捲軸行為難以在元件內部被攔截或偵測。

用 overflow: hidden 把滾動鎖在內層容器,就能:

精準監聽滾動事件(例如無限滾動、Lazy Load)。

控制滾動範圍(例如「列表滾動到底才載入更多」)。

  1. ⚡ 性能與重繪更穩定(減少 Reflow / Repaint)

當 < body> 捲動時,整個 DOM 都會重新計算位置與佈局,這會導致:

Reflow 開銷大

動畫不流暢

捲動時機容易抖動

若只讓內層 < div> 滾動,重繪範圍只在那個區塊內,效能更穩、更可預測。

  1. 🔄 頁面狀態可維持(回上一頁也能保留滾動位置)

在 SPA 中,如果每次路由切換都讓 < body> 滾動:

回上一頁時會回到頂端(滾動位置丟失)。

使用者體驗不佳。

但如果滾動交給「內層容器」,你就能記錄滾動位置,並在返回時還原它👇:

⚠️ **GitHub.com Fallback** ⚠️