图片优化
图片在网页数据的传输中占据了非常大的流量,如何优化图片,对于前端页面加载的性能极其重要。本文讲述了比较常见的几种优化图片的技巧。
图片格式介绍
(1)JPEG
JPEG 是 Joint Photographic Experts Group 的缩写,不支持透明度,常用于网站的 Banner 图。JPEG 使用的是一种有损图像质量的压缩算法,压缩的越狠,图片的质量损失也就越大,图片的尺寸也就越小。根据你网站所能忍受的图片质量,来相应的选择压缩比:
(2)PNG
支持透明度,支持无损压缩,一般图片的尺寸都比较大。
(3)GIF
适合放动画图片。
(4)WebP
🔥Google 2010 年提出的新的图像压缩格式算法,在 2013 年又推出 Animated WebP,即支持动画的 Webp。优点:更优的图像数据压缩算法、拥有肉眼识别无差异的图像质量、具备了无损和有损的压缩模式、Alpha 透明以及动画的特性。
PNG、JPG、WebP 压缩对比:
GIF 和 WebP 对比:
不同网络环境,加载不同尺寸图片
如下是京东网站首页占据 C 位的宣传图:
它的 URL 地址如下,你任意改变这张图片的 URL 里面的宽、高,放到浏览器里面重新进行请求,就可以得到相应大小的图片:
响应式图片
不同平台设备加载不同大小、甚至不同内容的图片!
CSS 媒体查询
@media all and (max-width: 600px) {
img {
width: 300px;
}
}
@media all and (min-width: 600px) and (max-width: 1200px) {
img {
width: 900px;
}
}
srcset、sizes、picture 和 source
(1)srcset
属性
img
标签的 srcset
属性定义了我们允许浏览器选择的图像集,以及每个图像的大小:
<img srcset="images/team-photo.jpg 1x,
images/team-photo-retina.jpg 2x,
images/team-photo-full.jpg 2048w,
images/team-photo-default.jpg"
src="team-photo.jpg">
上述代码,srcset
属性给出了四个图像的 URL。1x
或 2x
这个 x
代表 pixel density descriptor
,代表当当前设备的像素密度是标准像素密度的 1 倍或 2 倍时,去加载对应的图片,这个值可以是浮点数。2048w
的 w
代表 width descriptor
,也就是图片的以像素为单位的宽度,当浏览器的渲染器需要去渲染宽度为 2048 像素的图片的时候,就会使用这张图片,这个值必须是正整数。
最后一个图像 URL images/team-photo-default.jpg
没有带 x
或者 w
,这表示这张图片是一张候选图片,当 srcset
其它图片都没有匹配上的时候,那么就会使用这种图片。当然,候选图片是可选的,如果不提供,就会选择使用 src
图片作为默认图片。
(2)sizes
属性
srcset
提供了一个图片的候选集,但是选择哪个图片是浏览器决定的,我们无法灵活控制。如果想要自己根据屏幕的大小,来告诉渲染器去渲染多大尺寸的图片,可以引入 sizes
属性。
<img src="/files/16870/new-york-skyline-wide.jpg"
srcset="/files/16870/new-york-skyline-wide.jpg 3724w,
/files/16869/new-york-skyline-4by3.jpg 1961w,
/files/16871/new-york-skyline-tall.jpg 1060w"
sizes="((min-width: 50em) and (max-width: 60em)) 50em,
((min-width: 30em) and (max-width: 50em)) 30em,
(max-width: 30em) 20em">
sizes
的格式:媒体查询条件 目标值
。
上述的 sizes
属性表示,当屏幕宽度位于 50em ~ 60em 的时候,渲染所需图片宽度为 50em,当屏幕宽度位于 30em ~ 50em 的时候,渲染所需图片宽度为 30em,当屏幕宽度小于 30em,渲染所需图片宽度为 20em。当渲染器所需渲染的图片宽度确定的时候,再去 srcset
中去匹配最接近该宽度的图片 URL 即可。
目标值的单位可以是:
- 相对字体大小的单位:
em
或ex
- 绝对单位:
px
或cm
- Viewport(窗口) 百分比单位:
vw
(3)picture
和 source
srcset
和 sizes
可以让网站根据屏幕大小来加载**内容相同的(虽然也可以不同,但不应该这样用)**不同大小的图片,如果还想根据不同的屏幕,显示不同内容的图片,例如电脑上显示如下比较宽的图:
而手机上为了突出人物,显示比较瘦的图:
可以使用 <picture>
和 <source>
标签来解决这个问题:
<picture>
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
<source media="(min-width: 800px)" srcset="elva-800w.jpg">
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
上述代码的 <img>
标签是必须提供,否则不会显示任何图片,当 <source>
的媒体查询条件都不满足的时候,<img>
将会显示 src
所指向的 URL 图片。
除此之外,<picture>
标签还可以根据浏览器所能渲染的图片格式来选择不同的图片:
<picture>
<source type="image/svg+xml" srcset="pyramid.svg">
<source type="image/webp" srcset="pyramid.webp">
<img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
当浏览器按照 <source>
出现的顺序,依次探测是否满足条件,如果满足,就加载相应图片。
懒加载
有很多库可以实现懒加载图片,例如 lazysizes。对于每一张图片,需要确定在其原图内容还未被浏览器渲染出来之前,这张图应该显示什么占位符,目前有两个库可以生成图像的占位符。当然,如果对于所有图片,都像是用一个统一的图片作为占位符,也未尝不可。
LQIP
LQIP 就是 Low Quality Image Placeholders (低质量图像占位符) 的缩写。
SQIP
上述 LQIP 是基于像素的解决方案,而 SQIP 是 SVG-based LQIP (基于 SVG 的低质量图像占位符) 的缩写,其实基于 SVG 的,在任何设备上都看起来很清晰。
下图展示的是一个效果图:
换一种方式来表达图片
Data URL
对于一些较小的图片,可以将内容直接内嵌在 URL 中,常见格式如下:
data:[<mediatype>][;base64],<data>
mediatype
标识图片的格式,例如 image/jpeg
等。
Image sprites (雪碧图)
对于 HTTP 1.X 协议,雪碧图(即多张小图片合成一张大图)的加载方式,是很多网站都会采用的技巧,这种方式的缺点是,如果某个应用图标需要更新,那么整张大图都需要替换。
然而对于 HTTP 2.0 协议的到来,加载多张小图是比较推荐的做法,因为多张图片本身的下载都会复用同一个连接。
参考
扫描下面二维码,在手机端阅读: