嘿,大家好!我是今天的主讲人,很高兴能和大家一起聊聊前端性能优化里一个非常重要的环节——图片优化。别害怕,这玩意儿其实没那么玄乎,咱们把它掰开了揉碎了,保证大家听完之后都能成为图片优化大师(至少是入门级)。
今天咱们主要聊三个方面:响应式图片、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 缓存策略,可以减少重复加载图片的次数。
希望今天的讲座对大家有所帮助!记住,图片优化是一个持续的过程,需要不断地学习和实践。祝大家都能成为图片优化大师!