祐成

頁面太長讀者一直迷路?自動目錄導航,連手機都顧到

我想替一個很長的頁面加導航。從「自動目錄側欄」問起,一路追問「手機螢幕太窄怎麼辦」,最後用空心圓/實心圓圓點,找到一個手機和電腦共用的解。

朱祐成
· 11 分鐘閱讀 · 學習筆記
頁面太長讀者一直迷路?自動目錄導航,連手機都顧到
Image courtesy of The Metropolitan Museum of Art, Open Access

喬治・斐德烈・瓦茲《阿里阿德涅》(Ariadne),1894 年,油畫。瓦茲(George Frederic Watts,英國,1817–1904)以希臘神話人物阿里阿德涅為題——她給了忒修斯一束線團,讓他殺死牛頭怪後能循著線走出迷宮。這束「會帶你回頭的線」,正是本文導航設計的隱喻。現藏於紐約大都會藝術博物館。

一份很長的頁面,使用者往下捲、再往下捲,然後忘了自己在第幾段、上面講過什麼、下面還剩多少。捲動軸只告訴他「大概在中間」,幫不上忙。


自動目錄導航在解什麼問題

長內容會讓人迷路——長文件、長對話、長回答都一樣。一個好的目錄導航要做三件事:

  • 我現在在哪一段(捲到哪,目錄就高亮哪)
  • 上面下面還有多少(一眼看出整體進度)
  • 想回某段不用一直滾(點一下直接跳)

關鍵字是 scrollspy:用 getBoundingClientRect() 監看每個段落有沒有進入視窗,進入了就把目錄對應項目點亮。自動的部分則是用 JS 掃描頁面所有標題,動態生出目錄——新增段落會自動出現,不用手寫維護。


那條會跟著你走的線

最漂亮的一種做法,靈魂不在「高亮」,而在一條會跟著你滑動的線(Hakim El Hattab 的經典範例)。它在目錄旁邊放一條 SVG <path>,用 stroke-dasharray 的障眼法,只讓「目前可見段落」那一截線顯色:

// 先沿著每個目錄項目把整條線描出來,
// 記下每一段在線上的起點與終點
item.pathStart = tocPath.getTotalLength()

// 捲動時,只點亮可見區間的那一小段,其餘透明
tocPath.setAttribute(
  'stroke-dasharray',
  `1, ${pathStart}, ${pathEnd - pathStart}, ${pathLength}`
)

純 vanilla JS + SVG,零依賴。視覺上就像一支筆,滑到你正在讀的位置。


我的追問與發現

手機螢幕太窄,右側再放一條目錄會擠到內文,怎麼辦?

桌機好辦——版面兩側有留白,塞得下一條目錄。但手機畫面太窄,硬塞一條會壓縮主要內容。

一個常見的「進階解」是做成可收合的浮動迷你地圖:平常只是右邊緣一排很細的刻度,滑鼠移過去才展開成可點清單(就像某些聊天介面右側那條)。

但這裡有個硬傷:它靠 hover,而觸控裝置根本沒有 hover。 這是一個只在「滑鼠 + 桌機」成立的互動,搬到大多數人實際在用的手機上會直接失效。刻度也太細,撞到「大觸控區」的原則。

這正是「能力不到,就別用那個外型」的活教材——別做一個你的裝置兌現不了的互動。

那左邊或右邊只放空心圓和實心圓呢?手機也適合嗎?

這個問題是轉折點。純圓點:實心 ● = 你現在在的段,空心 ○ = 其他段,點一下跳過去。

為什麼它是第一個真正能「手機桌機同一套」的解

  • 沒有文字標籤 → 就不需要 hover 去「讀」它,hover 硬傷直接消失
  • 圓點可以包進大觸控熱區 → 視覺上是小圓點,但點擊範圍做到 30–40px,手指點得到
  • 超省寬度 → 一排圓點只佔右邊約 24px,手機也塞得下

這不是新發明,是老牌的 Layer-1 模式(iOS 的頁面圓點、輪播指示點都是同一招),可靠。

圓點在置中的窄欄,還是會壓到內文

實作後撞到一個細節:當內文是置中的固定寬度欄,而視窗只比它寬一點點時,兩側溝槽不夠塞圓點軌道,圓點就疊到內文上了。

修法很簡單:窄螢幕時,替內文保留一條右側軌道(多給一點 padding-right),讓圓點有自己的車道。一個 media query 就解決:

/* 窄螢幕:替圓點軌道保留右側空間 */
@media (max-width: 969px) {
  .wrap { padding-right: 48px; }
}

你可以怎麼用

  • 任何「長到會迷路」的頁面(長文、教學、條款、儀表板),都值得加一條 scrollspy 導航
  • 桌機版面有留白 → 用側邊目錄,甚至加一條會跟著走的墨線
  • 要照顧手機 → 改用純圓點:實心當前、空心其他、點擊跳段,一套 UI 走天下
  • 動手前先問一句:這個互動,手指點得到嗎? hover 是滑鼠的特權,別預設每個人都有滑鼠

延伸連結


一句話帶走

桌機能用的互動,不代表手機能用。hover 是滑鼠的特權;想做一套到底的 UI,先問「手指點得到嗎」。



📚 完整學習對話紀錄(想看完整脈絡可展開)

起點:替一個很長的頁面加導航

長頁面的痛點是「迷路」——讀者不知道自己在哪、上面講過什麼、下面還剩多少。我想替這種頁面加一個自動目錄導航。


Claude 的白話解釋:自動目錄 + 會跟著走的墨線

目錄導航的核心有三塊:

  1. 自動生成:JS 掃描頁面所有標題,動態建出目錄,新增段落自動出現
  2. scrollspy:用 getBoundingClientRect() 偵測哪個段落在視窗裡,點亮對應目錄項
  3. 點擊跳段:錨點連結 + 平滑捲動

進階版還可以加一條 SVG 墨線(Hakim El Hattab 的技法),用 stroke-dasharray 只讓「目前可見段落」那一截線顯色,視覺上像一支筆滑到你正在讀的位置。純 vanilla JS + SVG,零依賴。


我的提問:其他小螢幕尺寸 可以適合這種樣式嗎?

桌機放得下側邊目錄,那手機呢?右側再放一條會不會擠到內文?


Claude 的回答:能一半,但 hover 是硬傷

側邊目錄省寬度的進階做法,是收合成右邊緣的細刻度、滑鼠移過去才展開。優點是收合時幾乎不佔空間,能補上桌機到平板那段中間地帶。

但它本質是「滑鼠 + hover」的桌機設計:

  • 靠 hover 展開 → 觸控裝置沒有 hover,手機根本觸發不了
  • 刻度太細 → 手指點不準,撞到大觸控區原則

所以它沒有真正解決手機,只是把「有目錄」的範圍往下延伸到有滑鼠的裝置。真手機還是無解。

而且如果「寬螢幕一套、中螢幕一套、手機又一套」,就變成三套 UI——正好是「一致式設計:只做一套」最想避免的方向。


我的提問:或是直接在左邊或右邊 只出現 空心圓和實心圓 就好呢?這樣手機也就適合了嗎?

不放文字、不展開清單,就單純一排圓點:實心代表現在在的段、空心代表其他段。這樣手機是不是也能用?


Claude 的回答:會,這是第一個真正「一套 UI」的解

對,而且這是目前第一個能「手機桌機同款」的方案,原因很乾淨:

  • 圓點沒有文字標籤 → 不需要 hover 去讀它,hover 硬傷消失
  • 圓點可做大觸控熱區 → 視覺是小圓點,點擊範圍做大,手指點得到
  • 超省寬度 → 一排點只佔右邊約 24px,手機也塞得下

實心 ● = 當前段、空心 ○ = 其他段,點一下跳段,捲動時哪顆變實心就是「我在哪」。這是 iOS 頁面圓點那種老牌可靠模式,不是新發明。為了讓沒有視覺標籤的圓點對螢幕讀者也友善,每顆圓點補一個 aria-label(例如「跳到 第 4 段」)。


我又遇到的問題:圓點壓到內文

實作後發現,當內文是置中的固定寬度欄、視窗又只比它寬一點時,右側溝槽不夠,圓點疊到內文上了。


Claude 的回答:窄螢幕保留一條軌道

把圓點縮小、靠更邊,並在窄螢幕時替內文多保留一點 padding-right,讓圓點有自己的車道,就不會壓到內文。一個 media query 就搞定。驗證下來:手機捲到第 4 段,第 4 顆圓點變實心,內文和圓點之間還留著安全間距。


我學到的

從「自動目錄側欄」一路問到「手機怎麼辦」,最有價值的不是某個炫技,而是一個判準:桌機能用的互動,不代表手機能用。 hover 是滑鼠的特權,一旦想做「一套 UI 走天下」,最樸素的空心圓/實心圓反而是最穩的答案——因為它不依賴任何裝置才有的能力。