图片优化策略
WebP、雪碧图、Base64、懒加载、响应式图片的使用场景和实现
问题
前端图片优化有哪些常用策略?分别适用于什么场景?
解答
1. WebP 格式
WebP 比 JPEG/PNG 体积小 25-35%,支持透明和动画。
<!-- 使用 picture 元素做格式降级 -->
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="fallback">
</picture>
// 检测 WebP 支持
function checkWebpSupport() {
const canvas = document.createElement('canvas');
return canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0;
}
2. 雪碧图 (CSS Sprites)
将多个小图标合并成一张图,减少 HTTP 请求。
/* 雪碧图使用 */
.icon {
background-image: url('sprites.png');
background-repeat: no-repeat;
}
.icon-home {
width: 24px;
height: 24px;
background-position: 0 0;
}
.icon-user {
width: 24px;
height: 24px;
background-position: -24px 0;
}
.icon-settings {
width: 24px;
height: 24px;
background-position: -48px 0;
}
3. Base64 内联
小图片转 Base64 直接嵌入,省去请求。适合 < 2KB 的图片。
/* CSS 中使用 Base64 */
.logo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==');
}
// JS 转换图片为 Base64
function imageToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
4. 懒加载
图片进入视口时才加载,减少首屏请求。
<!-- 原生懒加载 -->
<img src="image.jpg" loading="lazy" alt="lazy image">
// Intersection Observer 实现懒加载
function lazyLoadImages() {
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); // 加载后停止观察
}
});
}, {
rootMargin: '50px' // 提前 50px 开始加载
});
images.forEach(img => observer.observe(img));
}
document.addEventListener('DOMContentLoaded', lazyLoadImages);
<!-- 配合使用 -->
<img data-src="real-image.jpg" src="placeholder.jpg" alt="lazy">
5. 响应式图片
根据设备屏幕加载不同尺寸的图片。
<!-- srcset + sizes -->
<img
src="small.jpg"
srcset="small.jpg 400w,
medium.jpg 800w,
large.jpg 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1000px) 800px,
1200px"
alt="responsive image">
<!-- picture 元素实现艺术指导 -->
<picture>
<!-- 移动端:裁剪后的竖版图 -->
<source media="(max-width: 768px)" srcset="mobile.jpg">
<!-- 平板:中等尺寸 -->
<source media="(max-width: 1200px)" srcset="tablet.jpg">
<!-- 桌面端:完整横版图 -->
<img src="desktop.jpg" alt="art direction">
</picture>
<!-- 高清屏适配 -->
<img
src="image.jpg"
srcset="image.jpg 1x,
image@2x.jpg 2x,
image@3x.jpg 3x"
alt="retina image">
策略选择参考
| 策略 | 适用场景 | 注意事项 |
|---|---|---|
| WebP | 所有图片 | 需要格式降级 |
| 雪碧图 | 小图标集合 | HTTP/2 下收益降低 |
| Base64 | < 2KB 小图 | 增加 CSS/HTML 体积 |
| 懒加载 | 长页面、图片列表 | 首屏图片不要懒加载 |
| 响应式 | 不同设备展示 | 需准备多套图片 |
关键点
- WebP 体积更小,用
<picture>做格式降级兼容旧浏览器 - 雪碧图减少请求数,但 HTTP/2 多路复用后优势减弱
- Base64 适合极小图片,过大会增加文档体积且无法缓存
- 懒加载用
loading="lazy"或 Intersection Observer,首屏图片除外 - 响应式图片用
srcset+sizes让浏览器自动选择合适尺寸
目录