在 GitHub 或技術文件網站上,常會看到標題 hover 時出現 link icon。點擊後會複製帶有 #{title-id} 的 URL;別人開啟連結時,頁面會直接捲到對應標題。網址雖然更新了,當前頁面卻不必重新載入。

這是什麼?

從 UX 角度看,點標題後留在同一頁並移到該段,是「頁內導覽」(in-page navigation);WAI 也用這個名稱描述連到頁面內容的導覽方式。指向特定標題的連結可稱為 jump link;能分享並讓別人直接抵達文章特定段落的 URL,則是「深層連結」(deep link)。這次的互動把兩者放在同一個標題操作裡:點擊會更新 URL fragment、捲動到定位並複製可分享的深層連結。當前頁面不會重新載入,也不需要 re-render 整篇文章;別人打開分享連結時,則會載入文章並定位到該標題。

標題錨點本來就有,還缺什麼?

盤點 blog 後,我發現 Astro 已經替文章標題產生 id,目錄也靠這些 id 跳轉。分享按鈕已有複製網址並加上 UTM 的寫法可以沿用;這次我另外用 Umami 的 copy-heading-link 事件,觀察標題連結入口有沒有人使用。

還有一個小取捨:中文標題產生的錨點放進網址時會被編碼,看起來不如英文 slug 俐落。若要全部改成英文,就得逐一替標題指定 id。我決定先接受這個網址樣子,之後再看實際使用情況。

手機沒有 hover,icon 要放在哪裡?

最初我想讓桌面在標題左側 hover 時才顯示 icon,手機則把淡色 icon 常駐在標題右側。手機沒有 hover,這看起來是個直接的補法;但放左邊就得讓標題縮排,放右邊則可能在標題換行時跑到不預期的位置。無論放哪裡,讀者都得多找一顆按鈕再點一次。

我正思考手機版該怎麼做,剛好在讀 Claude Code 文件,就順手測試它的標題互動。手機版沒有 link icon;直接點標題就會更新網址、捲到定位並複製連結,一次點擊完成定位和複製兩個動作。

點擊標題本身能不能取代手機 icon?

這個做法在桌面也成立,所以我讓所有尺寸都能直接點標題;桌面再保留 hover icon,提示標題可以操作。

於是手機不用專屬一套操作:文章內文的 h2 / h3 標題在所有尺寸都能點擊複製連結、更新網址錨點並捲到定位。我用 client-side script 處理點擊,不必額外寫 rehype plugin;複製連結、更新 URL 和捲動都在瀏覽器端完成,不會重新載入頁面,也不會觸發整篇文章 re-render。網址透過 history.replaceState 更新,不會每點一個標題就多一筆瀏覽紀錄;頁面用 scrollIntoView({ block: 'start' }) 捲動,也尊重 prefers-reduced-motion。行內連結和選取文字仍照常運作;滑鼠移到標題時會顯示 link icon,鍵盤焦點也會透過 :focus-visible 顯示相同提示。

點標題後被固定列蓋住,該留多少空間?

手機實測時,複製和錨點都正常,截圖卻發現標題被上方的 mobile title bar 蓋住。那一列是 position: fixed,捲動容器不知道它佔了 32px;我替標題加上 44px 的 scroll-margin-top,多出的 12px 留作閱讀間距。

桌面也微調了標題和 topbar 的距離,最後設成 12px。這裡的捲動容器是 <main>,topbar 在容器外;所以桌面標題只要離 <main> 上緣留 12px,手機則額外讓出 fixed title bar 的高度。數字量起來正確後,我還是看了實際畫面,才確認標題沒有被蓋住、留白也舒服。

複製提示應該放在哪裡?

一開始我想把複製提示放在畫面底部,讓 toast 短暫出現就好,不必太搶眼。實際點擊標題後,畫面會捲到該標題,視線也自然落在上半部;如果提示留在底部,讀者很容易錯過。於是我改把 toast 放到上方,但放得太高又可能蓋住剛定位的標題或右側目錄。

最後我把 toast 放在 topbar 下方,設定為 top: 52px; right: 4px。這會短暫遮到手機的第二列標題,寬螢幕時也可能碰到目錄標籤;訊息只停留幾秒,我接受這個取捨。Toast 負責讓當下的複製操作有明確回饋。

心得

我喜歡這種從自己閱讀習慣回頭補上的小功能:點標題就能到定位,也順手把連結帶走,桌面熟悉、手機直覺。對有長文的部落格,我會直接建議採用這個互動;它讓「標題錨點」從藏在網址裡的技術細節,變成讀者可以自然使用的入口。

讀到這裡,也可以直接點一下本文任一個標題試試:頁面會捲到該標題的位置,連結也會同步複製到剪貼簿。