---
title: "讀到一半畫面突然跳走？聊聊捲動錨定 overflow-anchor - Neil 的作品集"
description: 讀到一半，上方的圖片或廣告晚了幾秒才載入，畫面就整個往下跳。瀏覽器其實內建了「捲動錨定」來處理這件事。這篇用可以操作的範例實測它什麼時候有效、什麼時候幫不上忙，也分享我在自己網站找到的兩個實際例子，以及順手修掉的平滑捲動問題。
canonical_url: "https://neillin.com/blog/scroll-anchoring/"
last_updated: 2026-10-09
meta:
  author: Neil
  keywords: "無障礙網頁, 設計管理, 資料視覺化, UI, UX, 切版"
  "og:description": 讀到一半，上方的圖片或廣告晚了幾秒才載入，畫面就整個往下跳。瀏覽器其實內建了「捲動錨定」來處理這件事。這篇用可以操作的範例實測它什麼時候有效、什麼時候幫不上忙，也分享我在自己網站找到的兩個實際例子，以及順手修掉的平滑捲動問題。
  "og:image": "https://neillin.com/_og/s/o_4c3b18d1f1d1d143.png"
  "og:image:height": "600"
  "og:image:type": image/png
  "og:image:width": "1200"
  "og:title": "讀到一半畫面突然跳走？聊聊捲動錨定 overflow-anchor - Neil 的作品集"
  "twitter:image": "https://neillin.com/_og/s/o_4c3b18d1f1d1d143.png"
---

> Index of every page on this site: [llms.txt](https://neillin.com/llms.txt)

:::

# 讀到一半畫面突然跳走？聊聊捲動錨定 overflow-anchor

2026年10月9日  

[前端技術](https://neillin.com/blog?category=frontend "查看「前端技術」分類的所有文章")CSS前端開發無障礙瀏覽器支援

  

> 話說在前頭：文中的行為我都在 Chromium 上實測過，其他瀏覽器的細節可能不同，有講錯的地方歡迎指正。

## 前言

你一定遇過：文章讀到一半，上方的圖片或廣告晚了幾秒才載入，畫面突然往下一跳，剛剛讀到哪裡都找不到了。如果手指剛好要點連結，還可能點到別的東西。

這種畫面跳動對每個人都很煩，但對某些使用者影響特別大：

- **認知障礙或注意力容易分散的人**：好不容易專心讀到一個段落，一跳就斷掉了。
- **動作控制比較困難的人**：瞄準一個按鈕要花比較多時間，按下去之前畫面一動，就點錯了。
- **把畫面放大閱讀的人**：畫面上只看得到一小塊，跳一下就完全迷失位置。

瀏覽器其實內建了一個機制處理這件事，叫做**捲動錨定**（Scroll Anchoring），對應的 CSS 屬性是 `overflow-anchor`。它是 [CSS 與 HTML 技巧清單](https://neillin.com/blog/css-techniques-checklist)裡少數「預設就開著、很多人卻不知道」的功能，Safari 補上之後，三大瀏覽器都到齊了。

先看一下你的瀏覽器支援度：

你的瀏覽器支援度

- `overflow-anchor`偵測中（需要 JavaScript）

## 一、它在做什麼？

概念很簡單：瀏覽器會在畫面上挑一個元素當作「錨點」。上方的內容變高或變矮時，瀏覽器自動調整捲動位置，讓這個錨點留在畫面上的原位。

這個功能**預設就是開啟的**，你什麼都不用寫。需要關掉的時候才寫：

```
.chat-log {
  overflow-anchor: none;
}
```

## 二、動手試試

下面的方框是一篇文章，紫色那段是「你正在讀的段落」。先按「捲到第 5 段」，再按「模擬慢慢載入」，1.5 秒後最上面會多出一塊晚到的內容：

互動範例：先「捲到第 5 段」，再按「模擬慢慢載入」，看紫色那段會不會被推走

`overflow-anchor: none`（關掉捲動錨定）先幫晚到的內容預留空間（骨架畫面）

第 1 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 2 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 3 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 4 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 5 段：你正在讀這一段。

第 6 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 7 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 8 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 9 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 10 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 11 段：這是一段示範文字，假裝你正在讀一篇長文章。

第 12 段：這是一段示範文字，假裝你正在讀一篇長文章。

還沒載入。

此處為互動範例，請在網頁上操作。

建議照這幾種組合玩玩看：

| 情況 | 第 5 段會怎樣 |
| --- | --- |
| 捲到第 5 段，什麼都不勾 | 留在原位，捲動錨定生效 |
| 捲到第 5 段，勾「`overflow-anchor: none`」 | 被往下推 |
| 停在最上面，什麼都不勾 | **被往下推** |
| 停在最上面，勾「預留空間」 | 留在原位 |

第三種情況最值得注意：**捲動位置在最上面的時候，捲動錨定不會作用**。我實測在捲動位置是 0 的時候插入內容，下面的段落就是會被往下推。

## 三、實測：什麼時候有效、什麼時候幫不上忙

我另外用比較單純的頁面測了幾種情況：

| 情況 | 結果 |
| --- | --- |
| 已經往下捲，上方插入新內容 | 你正在看的位置不動 |
| 已經往下捲，上方一張沒設尺寸的圖片載入完成 | 不動 |
| 已經往下捲，上方的內容被移除 | 不動 |
| 已經往下捲，上方完全看不到的元素變高 | 不動 |
| 捲動位置在最上面，上方插入內容 | **被推走** |
| 捲動區塊設了 `overflow-anchor: none` | **被推走** |
| 畫面上**正在看的那個元素自己**變高 | 它下面的內容會被推走 |

最後一種的原因是：錨點通常就是你正在看的那個元素，它自己變高時，瀏覽器保住的是它的頂端，它下面的東西還是會被推下去。

另外，`overflow-anchor: none` 不一定要設在整個捲動區塊上。我實測只設在「會晚到的那一塊」上，瀏覽器就不會選它當錨點，其他段落照樣受保護。

## 四、什麼時候要關掉它？

大部分情況下，維持預設就好。需要關掉的通常是**你已經自己用 JavaScript 控制捲動位置**的地方，免得兩邊打架。例如：

- **聊天室、即時紀錄**：新訊息加在最下面，你的程式會在使用者停在底部時自動捲到最新一則。這時讓瀏覽器再補一次位置，反而會出問題。
- **自己實作的無限捲動或虛擬清單**：程式已經精準計算捲動位置了。

## 五、它只是保險，不是解法

捲動錨定能減少跳動，但前面也看到了，它有幫不上忙的時候。最根本的做法，還是**從源頭預留空間**，也就是範例裡「預留空間」那個選項：

```
<!-- 圖片寫上尺寸，載入前就先佔好位置 -->
<img src="photo.jpg" width="800" height="450" alt="…" />
```

```
/* 或是用 aspect-ratio、min-height 幫晚到的區塊留位置 */
.ad-slot {
  min-height: 250px;
}
```

預留了空間，連「停在最上面」這種捲動錨定幫不上忙的情況也不會跳。這也跟 Core Web Vitals 裡的 CLS（累積版面位移）有關。CLS 量的是使用者在畫面上看到的位移：我實測捲動錨定生效時，畫面上的內容沒有移動，CLS 是 0；但停在最上面、或關掉捲動錨定時，同樣插入 200px 的區塊，CLS 就是 0.25。預留空間才能讓兩種情況都不跳。

## 六、套用到我的網站

寫這篇時，我順便檢查了自己的網站，找到兩個實際的例子：一個是捲動錨定已經在默默幫忙，另一個是它幫不上忙、要從源頭修。

### 例子一：部落格列表的分類標籤

剛做好的 [部落格列表](https://neillin.com/blog/)，每篇文章下面都有一個可以點的分類標籤，點了會篩選出同分類的文章。我實測往下捲到第 10 篇，點它的「設計與 AI」標籤：

- **預設（捲動錨定開著）**：篩選後列表只剩 5 篇。瀏覽器把我點的那篇當成錨點，讓它留在原本的位置；它剛好是結果的第一篇，所以畫面上直接看到「共 5 篇文章」和結果開頭。
- **我把列表設成 `overflow-anchor: none` 對照**：頁面一下子變短，畫面停在一片空白的中段，結果開頭跑到視窗上方很遠的地方，要自己往上捲才找得到。

這裡**不需要加任何程式**，預設行為就是對的。不過它也有限制：如果點的那篇在結果裡不是第一篇，前面的結果就會在畫面上方。捲動錨定只負責「你剛剛看的東西不要跑掉」，不負責「讓你看到最重要的內容」。

### 例子二：產品頁的圖片沒寫尺寸

我用 PerformanceObserver 量網站各頁載入時的版面位移，並故意讓圖片晚 1.5 秒才載入，模擬網路慢的情況。結果 [產品頁](https://neillin.com/products/)的版面位移分數（CLS）是 **0.1263**，超過 Google 建議的 0.1。原因是產品頁的圖片都沒有寫 `width`、`height`，圖片載入前高度是 0，載入後才把下面的內容推開。

這剛好可以拿來驗證捲動錨定的兩面：

- **如果已經往下捲**，正在讀中段的文字，上方的圖片才載入：捲動錨定讓我正在看的標題留在原位（實測只差不到 1px）。
- **如果還在頁面最上面**，也就是剛打開頁面的時候：捲動錨定不作用，內容整個被往下推。

所以這裡要從源頭修。我寫了一個小腳本，讀出網站所有圖片的原始寬高存成一份清單，產品頁的 `<img>` 就依清單補上 `width`、`height`：

```
<img src="/images/accesserty-thumbnail.webp" width="1280" height="685" alt="…" />
```

搭配全站原本就有的 `img { max-width: 100%; height: auto; }`，瀏覽器會依寬高比例先把空間留好，畫面上的大小完全不變。修正後用同樣的條件再量一次，CLS 從 **0.1263 降到 0**。

為了避免之後新增圖片時忘記，我也在 build 的資料檢查裡加了一條：產品頁用到的圖片如果不在尺寸清單裡，build 就會失敗，提醒我重新產生清單。

## 七、順手修掉的：平滑捲動

檢查的過程中，我發現網站對整個頁面設了平滑捲動：

```
html {
  scroll-behavior: smooth;
}
```

但沒有判斷使用者是否開了「減少動態效果」。對動態敏感的使用者來說，點一下連結畫面就滑一大段，可能會頭暈。WCAG 2.3.3「互動產生的動畫」就是在講這件事。修正方式是只在使用者沒有要求減少動態效果時才開啟：

```
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}
```

網站右下角「回頁面頂端」按鈕用的 `window.scrollTo({ behavior: "smooth" })` 也一樣，CSS 管不到 JavaScript，要另外判斷：

```
const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
window.scrollTo({ top: 0, behavior: reduce ? "auto" : "smooth" });
```

## 結論

整理成幾句話：

- 捲動錨定預設就開著：上方內容變動時，讓你正在看的位置留在原地。
- 捲動位置在最上面時它不會作用，錨點自己變高時也擋不住。
- 自己用 JavaScript 控制捲動的地方，用 `overflow-anchor: none` 關掉，也可以只關掉會晚到的那一塊。
- 它只是保險，從源頭預留空間才是根本解法。
- 我的網站：部落格列表的分類標籤已經在受惠；產品頁的圖片補上寬高後，CLS 從 0.1263 降到 0。
- 順便檢查一下網站的 `scroll-behavior: smooth` 有沒有搭配 `prefers-reduced-motion`。

這篇算是「不用寫程式」的無障礙功能：瀏覽器默默幫忙，我們只要知道它的存在、別在不知情的情況下把它弄壞就好。

你在瀏覽網頁時，最常被哪種畫面跳動嚇到？歡迎一起討論！

## 延伸閱讀

- [只用 CSS 做輪播，無障礙夠嗎？拿我的 UI Kit 來對照](https://neillin.com/blog/css-carousel-a11y/)
- [中英文之間要不要打空白？text-autospace 讓瀏覽器自動補間距](https://neillin.com/blog/text-autospace/)
- [現代 CSS 與 HTML 技巧整理清單：115 個特性、支援度與實驗優先序](https://neillin.com/blog/css-techniques-checklist/)

## 相關連結

- [MDN — overflow-anchor](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor "另開新視窗")
- [MDN — Guide to scroll anchoring](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor/Guide_to_scroll_anchoring "另開新視窗")
- [web.dev — Cumulative Layout Shift（CLS）](https://web.dev/articles/cls?hl=zh-tw "另開新視窗")
- [WCAG 2.2 — 2.3.3 互動產生的動畫](https://www.w3.org/WAI/WCAG22/Understanding/animation-from-interactions "另開新視窗")
- [Can I use（瀏覽器支援度查詢）](https://caniuse.com "另開新視窗")

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://neillin.com/#website","@type":"WebSite","inLanguage":"zh-Hant-TW","name":"Neil 的作品集","url":"https://neillin.com/","workTranslation":{"@id":"https://neillin.com/en/#website"}},{"@id":"https://neillin.com/blog/scroll-anchoring/#webpage","@type":"WebPage","description":"讀到一半，上方的圖片或廣告晚了幾秒才載入，畫面就整個往下跳。瀏覽器其實內建了「捲動錨定」來處理這件事。這篇用可以操作的範例實測它什麼時候有效、什麼時候幫不上忙，也分享我在自己網站找到的兩個實際例子，以及順手修掉的平滑捲動問題。","name":"讀到一半畫面突然跳走？聊聊捲動錨定 overflow-anchor","url":"https://neillin.com/blog/scroll-anchoring/","isPartOf":{"@id":"https://neillin.com/#website"},"potentialAction":[{"@type":"ReadAction","target":["https://neillin.com/blog/scroll-anchoring/"]}]},{"@id":"https://neillin.com/#person","@type":"Person","jobTitle":"UI/UX 設計師","name":"Neil Lin","url":"https://neillin.com/","sameAs":["https://github.com/Neil-Lin"]},{"@id":"https://neillin.com/blog/scroll-anchoring/#/schema/blog-posting/1","@type":"BlogPosting","dateModified":"2026-10-09","datePublished":"2026-10-09","description":"讀到一半，上方的圖片或廣告晚了幾秒才載入，畫面就整個往下跳。瀏覽器其實內建了「捲動錨定」來處理這件事。這篇用可以操作的範例實測它什麼時候有效、什麼時候幫不上忙，也分享我在自己網站找到的兩個實際例子，以及順手修掉的平滑捲動問題。","headline":"讀到一半畫面突然跳走？聊聊捲動錨定 overflow-anchor","inLanguage":"zh-Hant-TW","keywords":"CSS, 前端開發, 無障礙, 瀏覽器支援","url":"https://neillin.com/blog/scroll-anchoring/","author":{"@id":"https://neillin.com/#person"},"mainEntityOfPage":{"@type":"WebPage","@id":"https://neillin.com/blog/scroll-anchoring/"},"publisher":{"@id":"https://neillin.com/#person"}},{"@id":"https://neillin.com/blog/scroll-anchoring/#/schema/breadcrumb-list/1","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"回首頁","item":"https://neillin.com/"},{"@type":"ListItem","position":2,"name":"部落格","item":"https://neillin.com/blog/"},{"@type":"ListItem","position":3,"name":"讀到一半畫面突然跳走？聊聊捲動錨定 overflow-anchor","item":"https://neillin.com/blog/scroll-anchoring/"}]}]}
```

## Sitemap

See the full [sitemap](https://neillin.com/sitemap.md) for all pages.
