網站使用「浮動導覽列」可提供友善的閱讀體驗,讓導覽列隨時保持在網頁最上方,訪客失焦時能重新找到方向。
不過這個設計後來發現有個隱藏的缺點,當網站使用了錨點後,訪客點擊錨點時,螢幕捲到的位置看起來怪怪的。
本站為了解決此現象,過去曾調高錨點的位置(放置隱藏的錨點),或是使用 JS 重新計算正確的座標。而最近多個案件都需要處理錨點異常的狀況,同時網頁版、行動版浮動導覽列高度不一樣的話,計算座標也是麻煩,於是研究了一下此現象有沒有更好的解決方法。
最後發現竟然使用 CSS 就可以做到簡單又完美的解法,請見本篇詳細的說明。
(圖片出處: peakpx.com)
1. 錨點的原理
錨點確切的運作方式,可參考這篇「神奇的html錨點,讓你的網頁在內部自由的跳轉」,重點整理如下:
瞭解以上原理後不難發現,浮動導覽列是有高度的,例如有 100px 高的話,那麼點擊錨點後,螢幕跳到定位點時,這個地方會被浮動導覽列遮住,只看得到定位點下方 100px 處的內容。
2. HTML 解法
這是最簡單的、也是我一開始的作法,建立看不見的定位點,也就是沒有文字內容的定位元素,然後接幾個換行標籤 <br/>,讓距離超過導覽列高度,再接要顯示的文字即可。
但這也是最不建議的解法,只要版型有變動,例如哪天沒用浮動導覽列了,或是導覽列高度改變了,那麼所有曾經使用錨點的文章,就得一篇篇手動改到崩潰。
3. JS 解法
後來比較聰明,改用 JS 自動處理,可避免前一個解法的窘境:
如果會寫 JS 的話,按照以上步驟進行即可。
根據這個討論串「Fixed page header overlaps in-page anchors」,原來 CSS3 有個選擇器:target 可以控制所有錨點,這樣就省事多了:
補充一下,上述 stackoverflow 討論串,每一個回答的參與者,有志一同幾乎都另外幫偽類區塊加了負值的 margin-top 或 padding-top,將這區塊往上拉回 Y 軸位置,我認為這是沒有必要的。
1. 最佳解
所以只要使用以下 CSS 程式碼,就能解決浮動導覽列遮住錨點位置的問題:
以上 ?? 請填入導覽列高度即可。
2. 四、處理 Blogger 行動版
如果是 Blogger 平台,只要懂得運用「Blogger 判斷式」還能同時處理網頁版與行動版的 CSS 設定。
例如將前面的 CSS 程式碼,加入以下的判斷式:
如此網頁版、行動版浮動導覽列引起的錨點問題,就能同時搞定了!
不過這個設計後來發現有個隱藏的缺點,當網站使用了錨點後,訪客點擊錨點時,螢幕捲到的位置看起來怪怪的。
本站為了解決此現象,過去曾調高錨點的位置(放置隱藏的錨點),或是使用 JS 重新計算正確的座標。而最近多個案件都需要處理錨點異常的狀況,同時網頁版、行動版浮動導覽列高度不一樣的話,計算座標也是麻煩,於是研究了一下此現象有沒有更好的解決方法。
最後發現竟然使用 CSS 就可以做到簡單又完美的解法,請見本篇詳細的說明。
(圖片出處: peakpx.com)
一、為何錨點位置錯誤
1. 錨點的原理
錨點確切的運作方式,可參考這篇「神奇的html錨點,讓你的網頁在內部自由的跳轉」,重點整理如下:
- ID 定位:任何 HTML 元素都可設定,例如 <div id="wfublog"></div>
- NAME 定位:只有 A 標籤可設定,例如 <a name="wfublog"></a>
- 超連結設定:將 A 標籤的超連結設定為井字號 "#" + 定位字串即可,例如 <a href="#wfublog">連結文字</a>
- 訪客點擊這個超連結後,螢幕頂端會自動跳到定位點,也就是放置了對應「id 定位」、或「name 定位」的位置
瞭解以上原理後不難發現,浮動導覽列是有高度的,例如有 100px 高的話,那麼點擊錨點後,螢幕跳到定位點時,這個地方會被浮動導覽列遮住,只看得到定位點下方 100px 處的內容。
2. HTML 解法
這是最簡單的、也是我一開始的作法,建立看不見的定位點,也就是沒有文字內容的定位元素,然後接幾個換行標籤 <br/>,讓距離超過導覽列高度,再接要顯示的文字即可。
但這也是最不建議的解法,只要版型有變動,例如哪天沒用浮動導覽列了,或是導覽列高度改變了,那麼所有曾經使用錨點的文章,就得一篇篇手動改到崩潰。
3. JS 解法
後來比較聰明,改用 JS 自動處理,可避免前一個解法的窘境:
- 監控 A 標籤的點擊事件,當超連結有錨點字串時才處理
- 點擊錨點後,計算導覽列高度,也計算定位點元素的 Y 軸座標
- 將螢幕捲到 (定位點元素的 Y 軸座標) - (導覽列高度) 之處,即可正確顯示錨點文字
如果會寫 JS 的話,按照以上步驟進行即可。
二、CSS 解法原理
根據這個討論串「Fixed page header overlaps in-page anchors」,原來 CSS3 有個選擇器
- 在定位點元素使用偽類
:before 製作看不見的區塊 - 為這個區塊設定高度,跟導覽列一樣高
- 這樣的設定,無形中自動增加了定位點元素的 Y 軸座標
- 使得點擊錨點後,定位點元素有了往下移動的效果,不再被導覽列遮住
補充一下,上述 stackoverflow 討論串,每一個回答的參與者,有志一同幾乎都另外幫偽類區塊加了負值的 margin-top 或 padding-top,將這區塊往上拉回 Y 軸位置,我認為這是沒有必要的。
三、CSS 範例程式碼
1. 最佳解
所以只要使用以下 CSS 程式碼,就能解決浮動導覽列遮住錨點位置的問題:
:target:before {
content: "";
display: block;
height: ??px;
}
以上 ?? 請填入導覽列高度即可。
2. 四、處理 Blogger 行動版
如果是 Blogger 平台,只要懂得運用「Blogger 判斷式」還能同時處理網頁版與行動版的 CSS 設定。
例如將前面的 CSS 程式碼,加入以下的判斷式:
<style>
:target:before {
content: "";
display: block;
<b:if cond='!data:blog.isMobile'>
height: ??px; /*這裡 ?? 填入 Blogger 網頁版導覽列高度*/
<b:else/>
height: ??px; /*這裡 ?? 填入 Blogger 行動版導覽列高度*/
</b:if>
}
</style>
如此網頁版、行動版浮動導覽列引起的錨點問題,就能同時搞定了!
更多 CSS 相關技巧: