1、你是否真的需要使用图片?
在项目引入图片前,首先需要问问自己,是否真的需要引入此图片,保证兼容性的前提下是不是可以使用如下替代方案:
1、iconfont
字体图标是一种全新的设计方式,更为重要的是相比位图而言,使用字体图标可以不受限于屏幕分辨率,冲着这一点就具有非常强的优势,而且字体图标还具有一个优势是,只要适合字体相关的CSS属性都适合字体图标,包括但不限于:font-size、color、text-shadow
优势
- 很容易任意地缩放、改变颜色、产生阴影
- 可以拥有透明效果
- 浏览器兼容性较好
- 本身体积更小
劣势
- 只能被渲染成单色或CSS3的渐变色
- 创作字体图标很耗时间
- 字体文件体积过大,直接影响页面加载性能,特别是加载一个包含数百图标的Fonts,却只使用其中几个图标
- 不同的设备浏览器字体的渲染会略有差别
建议
能使用字体图标尽量使用
2、css/css3
使用css,可以绘制出一些简单的图标,由于CSS3的普及和在各大浏览器的不断增强支持,使CSS具有更大的可能性和能力去绘制更多样化,更复杂的图标。可绘制包括但不局限于:三角形、气泡、心形...可参考文章
优势
- 占用空间小
- 无需网络请求,展现更快
劣势
- 兼容性需参考 具体实现中所用到的css属性的兼容性
建议
对应简单的的、且字体图标库中没有的图标,可尝试css实现
对展现要求更高的场景,可使用css
3、svg
VG图标实际上是一个服务于浏览器的XML文件,而不是一个字体或像素的位图。它是由浏览器直接渲染XML,在任何大小之下都会保持图像清晰。除此之外,SVG图像也有过字体图标的一个主要优势:拥有多个彩色图像的能力。
优势
- 可以随意修改大小,而且不会影响图标质量
- 可以使用CSS样式来自定义图标颜色,比如颜色、尺寸等效果
- 可以使用gzip的方式把文件压缩到很小
- 可以很精细的控制SVG图标的每一部分
劣势
- 需要了解使用制作软件绘制SVG图形或专业的SVG图形编辑软件
- 浏览器支持性一般,IE8和Android 2.1以及其以下浏览器不支持。
建议
随意修改大小,不会影响图标质量的小图标使用svg
4、Base64
优势
- 不增加请求数
劣势
- 通常比图片要大不到10%,增大css文件大小
- 每次加载页面都需要解码
- 难以维护
建议
小于3kb的小图标,可使用工具自动转换为base64,但同时要注意控制css整体的大小
5、canvas
使用canvas也可绘制出一些图案
暂时应用不多,在此仅提及一下
2、图片优化方案
1、减小图片大小
1、选择合适的图片格式
格式介绍:
- jpg有损压缩,压缩率高,不支持透明
- png支持透明,浏览器兼容好,无损压缩,体积大于jpg
- png8 —— 256色 + 支持透明
- png24 —— 2^24色 + 不支持透明
- png32 —— 2^24色 + 支持透明
- webp压缩程度更好,在ios webview有兼容性问题,pc端可在检测支持webp后使用 检测客户端是否支持webp
- gif 支持动图
| 类型 | 动画 | 压缩类型 | 透明度 |
|---|---|---|---|
| jpg/jpeg | 不支持 | 有损压缩 | 不支持 |
| png | 不支持 | 无损压缩 | 支持 |
| gif | 支持 | 无损压缩 | 支持 |
| webP | 不支持 | 无损压缩/有损压缩 | 支持 |
使用场景:
- jpg —— 大部分不需要透明图片的业务场景
- png —— 大部分需要透明图片的业务场景
- webp —— 安卓全部、pc端可在检测支持webp后使用
- gif —— 体积不大的动画,体积过大,建议用视频代替gif图
决策过程
注:svg介绍可见上文
2、确定合适的尺寸
不同终端对同一个图片需求不一样,可以根据终端加载不同的图片来节省没必要的流量。
原理
- 一倍图:当这个比率为1:1时,使用1个设备像素显示1个CSS像素。
- 二倍图:当这个比率为2:1时,使用4个设备像素显示1个CSS像素。
- 三倍图:当这个比率为3:1时,使用9(3*3)个设备像素显示1个CSS像素。
建议
- pc一般使用一倍图就可以
- 手机端建议使用二倍图
3、压缩图片
在线工具:
构建工具:
- gulp
- gulp-imagemin:支持PNG, JPEG, GIF and SVG
- webpack
- image-webpack-loader:支持PNG,JPEG,GIF,SVG和WEBP图像
- imagemin-webpack-plugin:可以优化一些因为loader局限性优化不了的图像,具体可见作者描述
2、减小图片请求数量
1、雪碧图
雪碧图也叫css精灵图,原理是把多张图片合成一张,然后在css中通过background-position来使用,以减小图片网络请求数,可通过以下工具合成:
在线工具:
-
合成雪碧图,并给出css代码,比较方便
构建工具
-
gulp
-
支持合成雪碧图,并输出less\sass\css\stylus文件
-
-
webpack
-
gulp.spritesmith的webpack版
-
解析css文件,从而生成雪碧图
-
建议
因为雪碧图比较难以维护(比如雪碧图中的某个小图标不再使用,删除后可能会影响其他图标的位置),建议用构建工具生成
2、缓存图片资源
通过设置浏览器的缓存,来减少图片请求数量,需服务端设置。
-
强缓存
-
Expires
Expires: Wed, 25 Jul 2028 19:19:42 GMT表示资源会在2028-07-25 20:20:42后过期,到时候需要再次请求资源了。由于 Expires 是依赖于客户端系统时间,当修改了本地时间后,缓存可能会失效
-
Cache-Control
Cache-control: max-age=259200表示的是一段时间间距,比Expires更加可靠,同时启用的时候Cache-Control 优先级更高
-
-
协商缓存
-
Last-Modified
last-modified: Wed, 17 Jun 2020 10:10:40 GMT表示被请求资源在服务器端的最后一次修改时间,当再次请求该资源的时候,浏览器的request header中会带上If-Modified-Since,向服务器询问该资源是否有更新。
-
ETag
etag: "FkGAN1LpxOYPOdwfOezDUP72sjwC.gz"每次文件修改后服务端那边会生成一个新的 ETag ,是一个唯一文件标识符,当再次请求该资源时候,浏览器的request header中会带上If-None-Match ,这值就是之前返回的ETag ,把这个值发送到服务器,询问该资源 ETag 是否变动,有变动的话,说明该资源版本需要更新啦,客户端不能继续用缓存里的数据了。
还可进行cdn缓存
-
3、懒加载图片
将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。
原理:
先将img标签的src链接设为同一张图片(比如空白图片),然后给img标签设置自定义属性(比如 data-src),然后将真正的图片地址存储在data-src中,当JS监听到该图片元素进入可视窗口时,将data-src赋值给真正的src。
实现方式
-
offsetTop方式图片是否出现在视窗内: offsetTop < clientHeight + scrollTop
-
getBoundingClientRect方式图片是否出现在视窗内: element.getBoundingClientRect().top < clientHeight
-
intersectionRatio:目标元素的可见比例,即 intersectionRect 占 boundingClientRect 的比例,完全可见时为 1 ,完全不可见时小于等于 0
-
Chrome 原生 lazyload 属性
<img src="https://source.unsplash.com/random/600" alt="" lazyload="on">非Chrome浏览器慎用
注意:监听滚动事件比较消耗性能,推荐进行节流
推荐阅读:
3、其他
1、预加载图片
针对我们将要用到的图片,可以选择预加载,这样可以提高用户体验。
实现方式
-
css的 background属性
// 设置图片在屏幕外 .preload-01 { background: url(img.png) no-repeat -9999px -9999px; } -
javaScript实现预加载
/** * 加载图片 * * @param {string} src 图片路径 * @return: promise */ function imgLoad(src) { // 用promise进行包装 return new Promise((resolve, reject) => { let img = new Image(); img.onload = () => { resolve(); }; img.onerror = err => { reject(err); }; img.src = src; }); }
2、双刃剑:display:none
<div style="display: none; background:url('c.png')">
<img src="a.png" style="display: none;">
<div style="display: none">
<img src="b.png">
</div>
</div>
经过测试,a.png、b.png、c.png在Chrome浏览器中都会加载
2、使用七牛云等第三方图片处理
如果项目使用了七牛云,建议使用七牛自带的图片处理api进行处理七牛云图片处理
建议:项目中的大图片可上传七牛
4、总结
所有,我们在拿到一张设计给的图片时,我们的思考过程应该是: