图像优化包含哪些内容(现代图片性能优化及体验优化指南 – 懒加载及异步图像解码方案)
本文是系列第四篇 。系列文章:
现代图片性能优化及体验优化指南 - 图片类型及 Picture 标签的使用 现代图片性能优化及体验优化指南 - 响应式图片方案 现代图片性能优化及体验优化指南 - # 缩放精细化展示及避免布局偏移 、拉伸图片资源 ,在我们的业务中可谓是占据了非常大头的一环 ,尤其是其对带宽的消耗是十分巨大的 。
对图片的性能优化及体验优化在今天就显得尤为重要 。本文,就将从各个方面阐述 ,在各种新特性满头飞的今天 ,我们可以如何尽可能的对我们的图片资源 ,进行性能优化及体验优化 。
懒加载/异步图像解码方案
继续下一个章节 。本章节 ,我们来讨论下图片的懒加载与异步图像解码方案 。
图片的懒加载
懒加载是一种网页性能优化的常见方式 ,它能极大的提升用户体验 。到今天 ,现在一张图片超过几 M 已经是常见事了 。如果每次进入页面都需要请求页面上的所有的图片资源 ,会较大的影响用户体验 ,对用户的带宽也是一种极大的损耗 。
所以 ,图片懒加载的意义即是,当页面未滚动到相应区域 ,该区域内的图片资源(网络请求)不会被加载。反之 ,当页面滚动到相应区域,相关图片资源的请求才会被发起 。
在过去 ,我们通常都是使用 JavaScript 方案进行图片的懒加载 。而今天 ,我们在图片的懒加载实现上,有了更多不一样的选择。
JavaScript 方案实现图片的懒加载
首先 ,回顾一下过往最常见的 ,使用 JavaScript 方案实现图片的懒加载 。
通过 JavaScript 实现的懒加载 ,主要是两种方式:
监听 onscroll 事件 ,通过 getBoundingClientRect API 获取元素图片距离视口顶部的距离 ,配合当前可视区域的位置实现图片的懒加载 通过 HTML5 的 IntersectionObserver API ,Intersection Observer(交叉观察器) 配合监听元素的 isIntersecting 属性 ,判断元素是否在可视区内 ,能够实现比监听 onscroll 性能更佳的图片懒加载方案但是 ,JavaScript 方案的一个劣势在于,不管如何 ,需要引入一定量的 JavaScript 代码 ,进行一定量的运算 。
到今天,其实我们有更多的其他便捷的方式去实现图片的懒加载。
使用 content-visibility: auto 实现图片内容的延迟渲染
首先 ,介绍一个非常有用 ,但是相对较为冷门的属性 -- content-visibility 。
content-visibility:属性控制一个元素是否渲染其内容,它允许用户代理(浏览器)潜在地省略大量布局和渲染工作 ,直到需要它为止 。
利用 content-visibility 的特性 ,我们可以实现如果该元素当前不在屏幕上 ,则不会渲染其后代元素 。
假设我们有这样一个 DEMO:
<div class="g-wrap"> // 模块 1 <div class="paragraph"> <p>Lorem Start!</p> <img src="https://cdn.yuucn.cn/wp-content/uploads/2023/03/1677616375-c830569728e3505.png" alt="" /> <p>Lorem End!</p> </div> // 模块 2 <div class="paragraph"> <p>Lorem Start!</p> <img src="https://cdn.yuucn.cn/wp-content/uploads/2023/03/1677616375-c830569728e3505.png" alt="" /> <p>Lorem End!</p> </div> // ... 连续几十个上述类似的结构 </div>只需要给需要延迟(实时)渲染的元素 ,设置简单的 CSS 样式:
.paragraph { content-visibility: auto; }我们来看一下 ,设置了 content-visibility: auto 与没设置的区别 。
如果 ,不添加上述的 content-visibility: auto 代码 ,页面的滚动条及滚动效果如下:
那么 ,在添加了 content-visibility: auto 之后 ,注意观察页面的滚动条及滚动效果:
可以看到滚动条在向下滚动在不断的抽搐,这是由于下面不在可视区域内的内容 ,一开始是没有被渲染的 ,在每次滚动的过程中,才逐渐渲染 ,以此来提升性能 。
Codepen Deom -- content-visibility: auto Image Load Demo
content-visibility: auto VS 图片懒加载
当然 ,其实使用 content-visibility: auto 并不能真正意义上实现图片的懒加载 。
这是因为,即便当前页面可视区域外的内容未被渲染 ,但是图片资源的 HTTP/HTTPS 请求 ,依然会在页面一开始被触发!
因此 ,这也得到了一个非常重要的结论:
content-visibility: auto 无法直接替代图片懒加载 ,设置了 content-visibility: auto 的元素在可视区外只是未被渲染 ,但是其中的静态资源仍旧会在页面初始化的时候被全部加载 。因此 ,它更像是一个虚拟列表的替代方案 。
关于 content-visibility 本文限于篇幅 ,没有完全展开 ,但是它是一个非常有意思且对渲染性能有帮助的属性 ,完整的教程,你可以看我的这篇文章 -- 使用 content-visibility 优化渲染性能
使用 loading=lazy HTML 属性实现图片懒加载
OK ,content-visibility 很不错 ,但是略有瑕疵 。但是,我们还有其他方式。
HTML5 新增了一个 loading 属性 。
到今天 ,除了 IE 系列浏览器 ,目前都支持通过 loading 属性实现延迟加载 。此属性可以添加到 <img> 元素中,也可以添加到 <iframe> 元素中。
属性的值为 loading=lazy 会告诉浏览器 ,如果图像位于可视区时 ,则立即加载图像 ,并在用户滚动到它们附近时获取其他图像 。
我们可以像是这样使用它:
<img src="" loading="lazy">这样 ,便可以非常便捷的实现图片的懒加载 ,省去了添加繁琐的 JavaScript 代码的过程 。
看看 loading=lazy 到今天(2023-02-26)的兼容性 ,还是非常不错的:
使用 decoding=async 实现图片的异步解码
除了 loading=lazy ,HTML5 还新增了一个非常有意思的属性增强图片的用户体验。那就是 decoding 属性 。
HTMLImageElement 接口的 decoding 属性用于告诉浏览器使用何种方式解析图像数据 。
它的可选取值如下:
sync: 同步解码图像 ,保证与其他内容一起显示 。 async: 异步解码图像 ,加快显示其他内容 。 auto: 默认模式,表示不偏好解码模式 。由浏览器决定哪种方式更适合用户 。上文其实也提及了 ,浏览器在进行图片渲染展示的过程中 ,是需要对图片文件进行解码的,这一个过程快慢与图片格式有关 。
而如果我们不希望图片的渲染解码影响页面的其他内容的展示 ,可以使用 decoding=async 选项 ,像是这样:
<img src="" decoding="async">这样,浏览器便会异步解码图像 ,加快显示其他内容 。这是图片优化方案中可选的一环 。
同样的 ,我们来看看到今天(2023-02-26) ,decoding="async" 的兼容性 ,整体还是非常不错的 ,作为渐进增强方案使用 ,是非常好的选择。
实际检验 loading=lazy 与 decoding=async 效果OK ,下面我们制作一个简单的 DEMO ,试一下 loading=lazy 与 decoding=async 的效果 。
我们准备一个拥有 339 个图片的 HTML 页面 ,每个图片文件的 src 大小不一 。
<div class="g-container"> <img src=""> <img src=""> // ... 339 个 </div>CSS 的设置也很重要,由于是纯图片页面 ,如果不给图片设置默认高宽 ,最页面刷新的一瞬间,<img> 元素的高宽都是 0 ,会导致所有 <img> 元素都在可视区内 ,所以,我们需要给 <img> 设置一个默认的高宽:
img { margin: 8px; width: 300px; height: 200px; object-fit: cover; }这样 ,再不添加 loading=lazy 与 decoding=async 的状态下 ,看看 Network 的表现:
我这里没有模拟弱网环境 ,网速非常快 ,可以看到 ,发送了 339 个图片资源请求 ,也就是全部的图片资源在页面加载的过程中都请求了 ,页面 Load 事件完成的时间为 1.28s。
好 ,我们给所有的图片元素 ,添加上 loading=lazy 与 decoding=async:
<div class="g-container"> <img src="" loading="lazy" decoding="async"> <img src="" loading="lazy" decoding="async"> // ... 339 个 </div>看看效果:
可以看到,这一次只发送了 17 个图片资源请求 ,页面 Load 事件完成的时间为 26ms 。
优化前 优化后 1.28s 26 ms1.28s 到 26ms ,效果是非常明显的,如果是弱网环境 ,对首屏加载性能的提升 ,会更为明显!
当然,实际我测试的过程也 ,也单独试过 decoding="async" 的作用 ,只是由于是纯图片页面 ,效果不那么明显 。感兴趣的同学 ,可以自行尝试。
总结一下
在本章节中 ,我们介绍了不同的方式实现图片的懒加载 、延迟渲染、异步解码 ,它们分别是:
通过 onscroll 事件与 getBoundingClientRect API 实现图片的懒加载方案 通过 Intersection Observer(交叉观察器)实现比监听 onscroll 性能更佳的图片懒加载方案 通过 content-visibility: auto 实现图片资源的延迟渲染 通过 loading=lazy HTML 属性实现图片懒加载 通过 decoding=async HTML 属性实现图片的异步解码当然 ,本文是现代图片性能优化及体验优化指南的第四篇 ,后续将给大家带来图片优化的最后一个章节:
可访问性 & 图片资源的容错及错误处理感兴趣的可以提前关注 。
最后
OK ,本文到此结束,希望本文对你有所帮助 ?
想 Get 到最有意思的 CSS 资讯 ,千万不要错过我的公众号 -- iCSS前端趣闻 ?
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏 。
如果还有什么疑问或者建议 ,可以多多交流 ,原创文章,文笔有限 ,才疏学浅 ,文中若有不正之处 ,万望告知 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!