嘿,大家好!我是今天的主讲人,很高兴能和大家一起聊聊前端性能优化里一个非常重要的环节——图片优化。别害怕,这玩意儿其实没那么玄乎,咱们把它掰开了揉碎了,保证大家听完之后都能成为图片优化大师(至少是入门级)。
今天咱们主要聊三个方面:响应式图片、WebP/AVIF 格式以及懒加载。这三板斧下去,你的网站图片性能至少能提升一个档次!
第一板斧:响应式图片,让图片“随机应变”
想象一下,你有一个特别高清的图片,放在电脑上看那是真漂亮,细节满满。但是,当用户用手机访问你的网站时,这么大的图片不仅加载慢,还浪费流量,简直是“杀鸡用牛刀”。响应式图片就是为了解决这个问题而生的。
简单来说,响应式图片就是根据用户的设备(屏幕尺寸、分辨率等)来加载不同尺寸或者不同清晰度的图片。这样,在大屏幕上就能看到高清图,在小屏幕上就能加载小图,既保证了视觉效果,又节省了流量。
怎么实现呢?主要有两种方式:
1. <picture>
元素
<picture>
元素允许你为不同的屏幕尺寸、分辨率等条件指定不同的图片资源。它的结构大概是这样的:
<picture>
<source media="(max-width: 600px)" srcset="small.jpg">
<source media="(max-width: 1200px)" srcset="medium.jpg">
<img src="large.jpg" alt="描述图片的文字">
</picture>
<picture>
:最外层的容器,包裹所有图片资源。<source>
:定义一个图片资源,media
属性定义媒体查询条件,srcset
属性指定符合条件的图片 URL。<img>
:兜底图片,如果没有任何<source>
匹配,就加载<img>
里的图片。alt
属性是必须的,用于描述图片内容,对 SEO 和可访问性很重要。
例子:
假设我们有三张图片:small.jpg
(600px 宽),medium.jpg
(1200px 宽),large.jpg
(原始尺寸)。
<picture>
<source media="(max-width: 600px)" srcset="small.jpg">
<source media="(max-width: 1200px)" srcset="medium.jpg">
<img src="large.jpg" alt="一只可爱的猫咪">
</picture>
当屏幕宽度小于等于 600px 时,加载 small.jpg
;当屏幕宽度小于等于 1200px 时,加载 medium.jpg
;否则,加载 large.jpg
。
srcset
的进阶用法:像素密度(DPR)
除了根据屏幕宽度选择图片,我们还可以根据像素密度(DPR,Device Pixel Ratio)来选择图片。DPR 表示一个 CSS 像素对应多少个物理像素。比如,DPR 为 2 的屏幕,一个 CSS 像素对应 2×2=4 个物理像素。
srcset
可以使用 x
描述符来指定像素密度。
<picture>
<source srcset="image.png 1x, image-2x.png 2x" type="image/png">
<img src="image.png" alt="示例图片">
</picture>
image.png 1x
:表示 DPR 为 1 的屏幕加载image.png
。image-2x.png 2x
:表示 DPR 为 2 的屏幕加载image-2x.png
。
sizes
属性
sizes
属性用于告诉浏览器,在不同的媒体查询条件下,图片显示的宽度。这个属性和 srcset
一起使用,可以帮助浏览器更准确地选择合适的图片。
<img
srcset="image-320w.jpg 320w,
image-480w.jpg 480w,
image-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="image-800w.jpg"
alt="示例图片">
srcset
:列出不同宽度的图片资源,并用w
描述符表示宽度。sizes
:列出媒体查询条件和对应的图片显示宽度。(max-width: 320px) 280px
:当屏幕宽度小于等于 320px 时,图片显示宽度为 280px。(max-width: 480px) 440px
:当屏幕宽度小于等于 480px 时,图片显示宽度为 440px。800px
:其他情况下,图片显示宽度为 800px。
src
:兜底图片。
2. <img>
元素的 srcset
和 sizes
属性
除了 <picture>
元素,我们还可以直接在 <img>
元素上使用 srcset
和 sizes
属性来实现响应式图片。这种方式更简洁,适用于简单的场景。
<img
srcset="small.jpg 600w, medium.jpg 1200w, large.jpg 2000w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 1000px"
src="large.jpg"
alt="一只可爱的猫咪">
srcset
:指定不同宽度的图片资源,600w
、1200w
、2000w
分别表示图片的宽度。sizes
:指定在不同媒体查询条件下,图片显示的宽度。(max-width: 600px) 100vw
:当屏幕宽度小于等于 600px 时,图片显示宽度为屏幕宽度的 100%。(max-width: 1200px) 50vw
:当屏幕宽度小于等于 1200px 时,图片显示宽度为屏幕宽度的 50%。1000px
:其他情况下,图片显示宽度为 1000px。
src
:兜底图片。
总结一下:
特性 | <picture> 元素 |
<img> 元素的 srcset 和 sizes 属性 |
---|---|---|
结构 | 复杂,需要嵌套 <source> 和 <img> 元素。 |
简单,直接在 <img> 元素上使用属性。 |
适用场景 | 复杂场景,需要根据不同的媒体查询条件选择不同的图片格式(例如 WebP 和 JPEG)或者不同的图片内容。 | 简单场景,只需要根据屏幕尺寸选择不同大小的图片。 |
灵活性 | 非常灵活,可以完全控制图片的加载逻辑。 | 相对灵活,但不如 <picture> 元素。 |
兼容性 | 兼容性良好,主流浏览器都支持。 | 兼容性良好,主流浏览器都支持。 |
第二板斧:WebP/AVIF 格式,让图片“瘦身”
传统的 JPEG、PNG 格式虽然应用广泛,但是压缩效率相对较低。WebP 和 AVIF 格式是更现代的图片格式,它们可以在保证图片质量的前提下,大幅度减小图片体积,从而加快加载速度。
1. WebP
WebP 是 Google 开发的一种图片格式,它支持有损压缩和无损压缩,可以提供比 JPEG 和 PNG 更好的压缩效果。
- 优势:
- 压缩率高:相同质量下,WebP 通常比 JPEG 小 25%-34%。
- 支持透明度:支持 Alpha 透明度,可以替代 PNG。
- 支持动画:支持动画,可以替代 GIF。
- 劣势:
- 兼容性:虽然主流浏览器都支持 WebP,但是一些老旧浏览器可能不支持。
2. AVIF
AVIF (AV1 Image File Format) 是一种基于 AV1 视频编码的图片格式。AV1 是一种开源、免版税的视频编码格式,AVIF 继承了 AV1 的优点,可以提供比 WebP 更高的压缩效率。
- 优势:
- 压缩率极高:相同质量下,AVIF 通常比 WebP 小 20%-30%。
- 支持 HDR:支持高动态范围(HDR)图像。
- 劣势:
- 兼容性:AVIF 的兼容性不如 WebP,一些老旧浏览器可能不支持。
- 编码复杂度高:AVIF 的编码复杂度较高,编码速度较慢。
如何使用 WebP/AVIF?
- 图片转换: 可以使用专业的图片处理软件(如 Photoshop)或者在线工具将图片转换为 WebP/AVIF 格式。
- 服务器配置: 确保你的服务器支持 WebP/AVIF 格式。
- 使用
<picture>
元素: 使用<picture>
元素,为支持 WebP/AVIF 的浏览器提供 WebP/AVIF 图片,为不支持的浏览器提供 JPEG/PNG 图片。
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="示例图片">
</picture>
- 浏览器会按照
<source>
元素的顺序,选择第一个支持的图片格式。 - 如果浏览器支持 AVIF,就加载
image.avif
;如果支持 WebP,就加载image.webp
;如果都不支持,就加载image.jpg
。
关于兼容性:
浏览器 | WebP 支持 | AVIF 支持 |
---|---|---|
Chrome | Yes | Yes |
Firefox | Yes | Yes |
Safari | Yes | Yes |
Edge | Yes | Yes |
Opera | Yes | Yes |
IE | No | No |
第三板斧:懒加载,让图片“按需加载”
想象一下,你的网站有很多图片,但是用户第一次访问时,只需要看到首屏的图片。如果一次性加载所有图片,会浪费大量的带宽和资源,导致页面加载速度变慢。懒加载就是为了解决这个问题而生的。
懒加载是指延迟加载页面上的图片,只有当图片出现在用户的可视区域内时才加载。这样可以减少初始加载时间,提高用户体验。
如何实现懒加载?
主要有两种方式:
1. Intersection Observer API
Intersection Observer API 是一种高效的监听元素是否进入可视区域的 API。它可以异步地监听目标元素与祖先元素或 viewport 的交叉状态。
const images = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
});
images.forEach(img => {
observer.observe(img);
});
document.querySelectorAll('img[data-src]')
:选择所有带有data-src
属性的<img>
元素。data-src
属性用于存储图片的真实 URL。IntersectionObserver
:创建一个 Intersection Observer 实例。entries
:一个包含 IntersectionObserverEntry 对象的数组,每个对象描述了一个被观察元素与根元素的交叉状态。observer
:IntersectionObserver 实例本身。
entry.isIntersecting
:判断元素是否进入可视区域。img.src = img.dataset.src
:将data-src
属性的值赋给src
属性,开始加载图片。img.removeAttribute('data-src')
:移除data-src
属性,防止重复加载。observer.unobserve(img)
:停止观察该元素。observer.observe(img)
:开始观察每个<img>
元素。
HTML 结构:
<img data-src="image.jpg" alt="示例图片">
2. loading
属性
HTML 提供了一个 loading
属性,可以用于实现图片的懒加载。这个属性有三个值:
lazy
:延迟加载图片,直到图片接近可视区域。eager
:立即加载图片,无论图片是否在可视区域内。auto
:由浏览器决定是否懒加载图片。
<img src="image.jpg" alt="示例图片" loading="lazy">
兼容性:
loading
属性的兼容性良好,主流浏览器都支持。
懒加载的注意事项:
- 首屏图片: 不要对首屏图片使用懒加载,否则会影响首屏加载速度。
- 占位符: 在图片加载之前,可以使用占位符来避免页面布局抖动。
- SEO: 确保搜索引擎能够抓取到懒加载的图片,可以使用
noscript
标签提供图片的备用链接。
总结:
今天我们聊了图片优化的三个方面:响应式图片、WebP/AVIF 格式以及懒加载。
- 响应式图片: 根据用户的设备选择合适的图片尺寸,节省流量,提高加载速度。可以使用
<picture>
元素或者<img>
元素的srcset
和sizes
属性来实现。 - WebP/AVIF 格式: 使用更高效的图片格式,减小图片体积,加快加载速度。
- 懒加载: 延迟加载可视区域外的图片,减少初始加载时间,提高用户体验。可以使用 Intersection Observer API 或者
loading
属性来实现。
一些额外的建议:
- 图片压缩: 在上传图片之前,可以使用专业的图片压缩工具(如 TinyPNG、ImageOptim)来减小图片体积。
- CDN: 使用 CDN (Content Delivery Network) 可以将图片分发到全球各地的服务器上,加快用户的访问速度。
- HTTP 缓存: 合理设置 HTTP 缓存策略,可以减少重复加载图片的次数。
希望今天的讲座对大家有所帮助!记住,图片优化是一个持续的过程,需要不断地学习和实践。祝大家都能成为图片优化大师!