我之前寫過一篇教學課程,討論如何使用 HTML、CSS 或 JavaScript 在網頁上預先載入圖片。我們費盡心思預先載入圖像的原因是為了向用戶提供更好的瀏覽體驗,這樣他們就不必等待圖像加載。
改善使用者體驗的相同概念也適用於延遲載入圖片。當我們瀏覽網站時,圖像是影響頁面重量的最大因素之一。以最佳方式加載它們可以提高效能並節省頻寬。
在本教程中,我們將了解延遲載入圖片的不同方法。
我們將透過了解為什麼您應該為延遲載入圖片而煩惱來開始本教學。假設您正在為一位攝影師建立一個作品集網站,他們在一個頁面上展示了所有最好的圖像。
並不是每個人都會滾動到頁面底部來查看所有圖像。但是,圖像仍會由使用者的瀏覽器下載。這在下面的 CodePen 演示中很明顯:
即使您沒有滾動超過上面演示中的第一個圖像,您也會看到瀏覽器已加載所有圖像。以下瀏覽器開發人員工具中網頁標籤的螢幕截圖顯示發出了 38 個請求,傳輸了大約 2.5MB 的資料。瀏覽器總共下載了 19 個圖像,重定向使請求數量增加了一倍。
#我們現在將嘗試改進或最佳化圖像載入以節省資源。
延遲載入映像的最簡單方法涉及使用 loading
屬性。所有現代瀏覽器都支援圖像上的loading
屬性,該屬性可用於指示瀏覽器防止加載不在螢幕上的圖像,並且僅在用戶滾動到足夠近以使其可見時才開始加載它們。 p>
loading
屬性可以接受兩個可能的值。第一個值是 eager
,它告訴瀏覽器立即載入圖像,即使它目前不在視窗內。這是瀏覽器的預設行為。
第二個值是 lazy
,它告訴瀏覽器推遲載入圖像,直到它到達距離視窗的特定距離。此距離由瀏覽器定義。將 loading
屬性的值設為 lazy
可能會為客戶端節省頻寬。
請務必記住,瀏覽器僅延遲載入目前在視窗中不可見的圖像。通常,網頁上的圖像與其他文字一起放置,將它們推到視口之外。在這種情況下,您不需要執行任何特殊操作來確保映像延遲載入。
但是,請考慮本教程中的範例,其中網頁僅包含圖像。在這種情況下,如果您希望延遲載入圖像,那麼提及圖像的大小就變得非常重要。否則,所有圖像最初的寬度和高度都將為零。這將使瀏覽器認為所有圖像在視窗中都可見,並且會立即載入所有圖像。
在這種情況下,明確指定影像寬度和高度會將某些影像推出視口。您可以使用 width
和 height
HTML 屬性或在 CSS 中自由指定圖片尺寸。
這是延遲載入圖片的標記:
<img loading="lazy" src="https://picsum.photos/id/628/1080/1080" width="600" height="600">
正如我之前所說,您也可以在 CSS 中指定圖片尺寸,並從標記中刪除 width
和 height
屬性:
<img loading="lazy" src="https://picsum.photos/id/628/1080/1080">
對應的 CSS 為:
img { width: 600px; height: 600px; }
以下 CodePen 示範展示了延遲載入的實際效果:
我的瀏覽器開發者工具中的網頁標籤顯示,這次只下載了四張影像,傳輸的資料量約為 450 kB。頁面上共有 19 張圖片,這意味著另外 15 張圖片將被延遲下載。就頻寬而言,這意味著節省了約 80%。
#這裡要記住的一件重要事情是,即使不涉及腳本,映像的延遲載入也僅在啟用 JavaScript 時才有效。這樣做是為了防止透過策略性放置的圖像來追蹤用戶的滾動位置。
瀏覽器如何決定何時應該下載應該延遲載入的圖片?觸發延遲載入影像下載的確切條件因瀏覽器而異。然而,兩個主要因素似乎是與視口的距離和網路速度。
如果您想要精確控制延遲載入圖片的下載時間,則必須使用 JavaScript。
现在我们将学习如何使用 JavaScript 延迟加载图像。这将使我们能够更好地控制整个过程。如果您认为默认的延迟加载不够激进,您可以使用 Intersection Observer API 创建自己的延迟加载脚本。
在编写任何 JavaScript 之前,我们需要对标记进行一些更改:
<img class="lazy-load" data-src="https://picsum.photos/id/628/1080/1080">
我们的 img
标签现在将包含一个名为 lazy-load
的类,以帮助我们识别哪些图像需要延迟加载。 img
标签将使用 data-src
属性来跟踪图像路径,而不是 src
属性。这会阻止图像立即开始下载。
Intersection Observer API 允许我们检测目标元素是否与其任何祖先元素或文档的视口相交。我们将使用 IntersectionObserver()
构造函数来创建 IntersectionObserver
对象。该构造函数接受回调函数作为其第一个参数,并接受一个用于自定义观察者行为的可选对象作为第二个参数。
我们传递给构造函数的回调函数接收两个参数。第一个是相交元素的数组,第二个是观察者本身。自定义选项允许您指定要检查交集的根元素、向根元素添加额外偏移值的根边距以及确定浏览器何时开始报告交集的阈值。
这是我们的交叉点观察者对象的代码:
function preload_image(img) { img.src = img.dataset.src; console.log(`Loading ${img.src}`); } const config_opts = { rootMargin: '200px 200px 200px 200px' }; let observer = new IntersectionObserver(function(entries, self) { for(entry of entries) { if(entry.isIntersecting) { let elem = entry.target; preload_image(elem); self.unobserve(elem); } } }, config_opts);
我在根元素(本例中为视口)的所有边上提供了 200 像素的边距。只要任何图像位于视口 200 像素范围内,我们的交叉点观察器就会激活。默认情况下,阈值设置为 0。值为零意味着只要图像的一小部分位于我们指定的范围内,就会调用 preload_image()
函数。 unobserve()
方法告诉浏览器停止观察该特定图像以进行进一步的交叉。
preload_image()
函数获取图像的 data-src
属性的值,并将其应用于 src
属性。这会触发我们图像的下载。
我们现在需要做的就是查询文档中的所有图像,然后告诉观察者观察它们是否有交集。这是为我们实现这一目标的代码。
let images = document.querySelectorAll('img.lazy-load'); for(image of images) { observer.observe(image); }
您是否注意到我们正在使用 img.lazy-load
选择器来查询我们的图像?这个类可以帮助我们轻松识别所有想要延迟加载的图像。没有此类的图像将正常加载。
这是一个 CodePen 演示,用于查看我们的图像是否确实延迟加载。
这次,我的浏览器开发者工具中的网络选项卡显示,之前只下载了两张图片,总共传输的数据量约为 192 kB。与原始演示相比,我们的带宽节省现已高达 92%。
我承认我已经让交叉观察者变得非常激进,只加载非常接近视口的图像。然而,这就是您自己实现该功能的美妙之处。
延迟加载图像对每个人来说都是双赢的。它将减少服务器的负载,同时节省用户的带宽。请记住,数据,尤其是移动数据,在世界上的某些地方非常昂贵。
现在浏览器原生支持延迟加载图像,只需对标记进行微小更改即可充分利用该功能。浏览器还足够智能,可以根据网络速度和图像位置确定延迟加载图像的理想时间。您还可以使用 Intersection Observer API 相对轻松地自行实现该功能。
这里要记住的一件重要事情是,如果用户端禁用 JavaScript,这些技术都将不起作用。
以上是使用 HTML 和 JavaScript 高效能載入圖像的詳細內容。更多資訊請關注PHP中文網其他相關文章!