什麼 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;
}
這種設計有一個核心目標:
👉 主框架不動、內容切換流暢、狀態不重置。
🧱 為什麼「外層不滾動」能讓結構更穩定?
- 🪄 保持主框架穩定(Header / Sidebar 不會跳動)
如果整個
都可以滾動,當內容切換時:捲軸長度可能改變,導致頁面「跳一下」。
固定在上方的 header、側邊選單位置可能跟著晃動。
用 overflow: hidden; 固定外層高度後,主框架就變成「穩如山」:
<App> ← 不會滾動
├─ <Header> ← 固定
├─ <Sidebar> ← 固定
└─ <RouterView> ← 捲動在這裡
- 📏 控制滾動行為更精準(誰滾動你說了算)
如果讓整個
滾動,會產生以下問題:元件之間爭奪滾動權(像對話框、Drawer、下拉選單等會受干擾)。
捲軸行為難以在元件內部被攔截或偵測。
用 overflow: hidden 把滾動鎖在內層容器,就能:
精準監聽滾動事件(例如無限滾動、Lazy Load)。
控制滾動範圍(例如「列表滾動到底才載入更多」)。
- ⚡ 性能與重繪更穩定(減少 Reflow / Repaint)
當 < body> 捲動時,整個 DOM 都會重新計算位置與佈局,這會導致:
Reflow 開銷大
動畫不流暢
捲動時機容易抖動
若只讓內層 < div> 滾動,重繪範圍只在那個區塊內,效能更穩、更可預測。
- 🔄 頁面狀態可維持(回上一頁也能保留滾動位置)
在 SPA 中,如果每次路由切換都讓 < body> 滾動:
回上一頁時會回到頂端(滾動位置丟失)。
使用者體驗不佳。
但如果滾動交給「內層容器」,你就能記錄滾動位置,並在返回時還原它👇: