【HTML】解決 Lazy loading 導致滾動定位不準的問題

【HTML】解決 Lazy loading 導致滾動定位不準的問題

本篇重點

  • 解決 Lazy loading 導致 .scrollIntoView() 滾動定位不準的問題
  • 檢查目標元素是否進入視窗的方式
  • .getBoundingClientRect()window.innerHeight.clientHeight 的應用

在開發「點擊回覆文章按鈕後自動滾動至留言區」的功能時,原本使用 .scrollIntoView({ behavior: 'smooth' }) 來實現平滑滾動的效果。但在實際測試時發現,滾動的位置沒有準確對齊留言區。檢查後發現,因為頁面中的圖片使用了 loading="lazy" 機制,導致圖片尚未載入時不會佔據實際高度,進而影響瀏覽器對滾動位置的計算,造成滾動偏移的問題。

js
1
2
3
4
$('#reply').click(function scrollToComment() {
const commentSection = document.getElementById("comment");
commentSection.scrollIntoView({ behavior: 'smooth' });
});

健忘筆記

以前都是使用套件來實現 Lazy loading 機制,現在 HTML 已經內建此機制,詳細可查看 【MDN】Lazy loading 介紹

解決方法

檢查目標是否進入視窗

在滾動後使用 setTimeout,並檢查目標元素是否進入視窗。如果未進入視窗範圍,則重新執行滾動,確保用戶能夠正確移動到留言區。

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$('#reply').click(function scrollToComment() {
const commentSection = document.getElementById("comment");
commentSection.scrollIntoView({ behavior: 'smooth' });

setTimeout(() => {
if (!isElementInViewport(commentSection)) {
scrollToComment();
}
}, 300);
});

function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight)
);
}
  1. 初次滾動:scrollIntoView({ behavior: 'smooth' }) 觸發滾動效果。
  2. 延遲檢查:使用 setTimeout 延遲 300ms,讓瀏覽器有時間載入 Lazy Load 圖片並重新計算頁面高度。
  3. 可視範圍判斷:透過 isElementInViewport() 檢查 comment 是否確實進入視窗範圍。
  4. 二次滾動:如果 comment 仍未進入視窗,則再次執行 scrollToComment(),確保滾動到正確位置。

健忘筆記

.getBoundingClientRect():取得某個元素相對於視窗的位置和元素大小(單位:px),可用來判斷元素是否出現在畫面中

  • top:元素頂部與視窗頂部的距離
  • bottom:元素底部與視窗頂部的距離
  • left / right:元素左右邊與視窗邊界的距離
  • width / height:元素的寬度與高度

window.innerHeight:取得目前瀏覽器「視窗可視區域」的高度(單位:像素 px),包括了內容區域 + 捲軸的高度(如果有捲軸),無論有沒有捲動網頁值都不會變

document.documentElement.clientHeight:取得目前瀏覽器「視窗可視區域」的高度(單位:像素 px),和 window.innerHeight 最大的差異是不包含捲軸的厚度及相容性較好

固定圖片的高度

固定圖片的高度後,瀏覽器在計算滾動位置能提前保留圖片所佔的空間,避免圖片載入後高度變化影響整體排版和捲動位置,進而解決滑動定位不準確的問題。但這個方法也有問題存在,若網站中的圖片尺寸不一(例如橫圖、直圖混排),全部統一設定固定高度可能造成畫面留白、不均衡,影響整體版面;若在 RWD(響應式網頁設計)中,圖片的顯示尺寸通常會根據螢幕寬度自動調整,強制設定固定高度(例如 height: 300px),會讓圖片失去原有比例,產生壓縮或拉伸的問題。

結論

我目前是用 setTimeout 搭配檢查目標元素是否進入視窗的方式,來解決 Lazy loading 導致滾動定位不準的問題。雖然這方法暫時能用,但感覺不是最佳解😅

如果有更聰明、簡單、穩定的解法,麻煩一定要留言分享給我!🙏🏻

延伸閱讀

作者

健忘工程師

發表於

2025-04-14

更新於

2025-04-14

許可協議


你可能也想看

【Html】自定義屬性:data-* 的命名規則和取值方法
【HTML】button 在 form 裡和在 form 以外的差別
【HTML】解析 <a> 的 rel 屬性

評論

複製完成