这可能是个别人写过很多次的话题,但貌似由于兼容性的原因?图标的显示还是用着 Iconfont 或者 CSS Sprite 的形式?
希望通过自己新瓶装旧酒的方式能重新引导一下问题。

SVG vs Image

比方说现在要做下图这样的视觉效果:

分析:可能需要三张图片

  1. 鼠标移入时的背景图
  2. 渐变色前景图
  3. 鼠标移入时白色前景图

独立图像

现在对比一下背景图使用图片与使用 SVG 格式的体积大小(做图的时候拿错颜色了,其他都一样,能说明道理就行,见谅见谅)

可以看出,在肉眼感觉差异不大的情况下,WebP 格式体积最小,其次是 SVG,而 PNG 的体积过大。

这个 SVG 是在 Sketch 设计稿中导出来的,源码包含了很多冗余无效的代码,实际上是可以优化的,如下。

内部源码

优化后

优化后大约可以减去 1K 个字符。当然这个需要内联使用(Inline SVG)

CSS Sprite

使用 CSS Sprite 的方式可以减少 HTTP 请求,貌似还可以减少总体图片体积。
这里用前景图来对比一下,实际上背景图和前景图都可以合成一张 sprite。

可以看出,CSS Sprite 的体积比 Inline SVG + CSS 的方式大很多。

SVG vs Image 结论

绿色部分表示 SVG 比 Image 略胜一筹的地方,黄色部分表示有所欠缺的地方,灰绿色表示差不多。

1、如今已接近 2019 年了,对于 IE9 (2011年) 这种古老的浏览器都支持 SVG,所以再过多强调更低的兼容性也没有什么意思。
2、Inline SVG 在浏览器应该是被渲染成 DOM 节点,所以关于 DOM 节点的性能优化都有必要注意;一个 SVG 图像可能就会有很多路径,即 DOM 节点,太多的 DOM 节点必然会影响浏览器的渲染性能及内存占用,而纯位图的渲染方式应该是没有这方面的顾虑。(DOM 数量影响参考:Google WEB 开发者文档)

综上结论:

除开复杂图像,选择 Inline SVG 或者 <img/> 标签的方式引入 SVG,会比使用 独立图像 或 组合图像 (CSS sprite) 的方式更好。

SVG vs Iconfont

书写对比

首先看下 Iconfont 与 SVG 图标的使用方式,来源 阿里 Iconfont 平台

很明显 SVG Sprite 使用起来没有 Iconfont 方便,需要写 3 行代码, 而后者只需要写 1 行。
当然上面的不是重点,重点是下面的换色与多色支持

换色与多色支持

换色

1、Iconfont 通过 CSS color 可以轻松更换图标颜色。

2、而 SVG Sprite 比较麻烦,SVG Sprite 的代码原理如下。

// 定义 symbol
<svg>
<symbol id="icon-arrow-left" viewBox="0 0 1024 1024">
<path d="M694 ... 44.576-45.952"></path>
</symbol>
<symbol id="icon-arrow-right" viewBox="0 0 1024 1024">
<path d="M693 ... 0-0.48-46.4"></path>
</symbol>
</svg> // 使用
<svg><use xlink:href="#icon-arrow-left"/></svg>
<svg><use xlink:href="#icon-arrow-right"/></svg>

渲染出来的 DOM 结构是这样的:

渲染在了 Shadow DOM 中(关于 Shadow DOM 的知识可以阅读下这篇文章或这篇),
这样的 DOM 元素样式就具有了作用域,外面的 CSS 对 shadow-root 内的元素不会生效,
如果想要更换元素的颜色,需要使用 /deep/ 来穿透添加样式,如下。

svg /deep/ path {
fill: red;
}

当然,实际上在只需要在父级元素上添加 fill: red 这样的 CSS 也能起到同样的效果,里面的元素会继承父级的样式。

PS: /deep/ 是 shadow DOM v0 的写法,v1 已经把这样的写法抛弃了,实际上支持 v1 的 shadow DOM, 父级的样式可以直接作用在 shadow-root 里面的元素。

多色支持

1、Iconfont 是不支持多色图标的。

2、而 SVG Sprite 可以利用 CSS 变量或 shadow DOM 的方式支持多色图标,shadow DOM 的方式上面已经说明,下面借用他人的文章解释 CSS 变量实现多色,如下。

不过使用 CSS 变量或 shadow DOM 的方式兼容性都不好,

  1. CSS 变量:Edge15+
  2. shadow DOM:更差。兼容性列表

3、Inline SVG 可以良好地支持多色及多色变化。

渐变色支持

Iconfont 与 SVG Sprite 不支持渐变色。
Inline SVG 支持渐变色,并且兼容性良好。

渲染无抖动

使用 Iconfont,因为字体文件是异步加载的,所以在字体文件还没有加载完毕之前,图标位会留空,加载完毕后才会显示出来,这个过程就会出现向下图(来自 GitHub blog)这样的抖动,而 SVG Sprite 或 Inline SVG 内联加载则不会出现这样的抖动。

当然,Iconfont 也可以内联加载,不过需要转换成 base64 同样式表一起加载,转换后的文件体积则会变为原来的 1.3 倍左右
这是由 base64 编码决定的(编码知识链接)。

字体转换成 base64 的一个在线工具:https://transfonter.org/

体积较大

这个是 SVG 对比于 Iconfont 的一个不足之处,如下图。

Inline SVG 与 SVG Sprite 体积差不多。

开发成本

三者的开发成本都差不多,不过 SVG 的两种方式都需要前期做些配置,后期开发就会顺手很多(单页应用)。

以 vue + vue cli 为例说明 Inline SVG 便捷使用。

1、 配置 Webpack loader:

{
// 排除需要转换成 Inline SVG 的目录
exclude: [resolve('src/svgicons')],
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
// 指定特定的目录用于 Inline SVG
include: [resolve('src/svgicons')],
test: /\.svg$/,
use: [
// 读取 SVG 源代码
{ loader: 'raw-loader' },
// 精简优化 SVG 源代码
{
loader: 'svgo-loader',
options: {
plugins: [
{ removeTitle: true },
{ removeViewBox: false },
{ removeDimensions: true },
// ...其他参数
]
}
}
]
}

2、 创建 SvgIcon.vue 组件:

<template>
<div class="svg-icon">
<div class="svg-icon-wrapper" v-html="icon"></div>
</div>
</template> <script>
export default {
name: 'SvgIcon',
props: {
name: {
type: String,
required: true,
},
},
data () {
return {
icon: this.getIcon(),
}
},
watch: {
name () {
this.icon = this.getIcon()
},
},
methods: {
getIcon () {
return require(`@/svgicons/${this.name}.svg`)
},
},
}
</script> <style lang="stylus" scoped>
.svg-icon {
overflow hidden
display inline-block
width 1em
height 1em
&-wrapper {
display flex
align-items center
>>> svg {
width 100%
height 100%
fill currentColor
}
}
}
</style>

3、使用:

<SvgIcon name="arrow-right" />

SVG vs Iconfont 结论

应该是 Inline SVG vs SVG Sprite vs Iconfont 的结论,如下图。

综上结论

选择 Inline SVG 或许是一个不错地选择去替代 Iconfont 的使用方式。

扩展阅读

  1. GitHub 网站很早之前已经将图标的展示方式由 Iconfont 转成了 Inline SVG, 这一篇文章是他们的描述:
    https://blog.github.com/2016-...
  2. 很早的一篇文章关于两者的对比:https://css-tricks.com/icon-f...

最后

欢迎各抒己见谈论一下对 SVG 和 Iconfont 的看法,优缺点,欢迎留言。

然后,本文同步发表于【凹凸实验室博客】或微信公众号,欢迎关注我们,么么哒。

SVG vs Image, SVG vs Iconfont的更多相关文章

  1. 【翻译svg教程 】svg 的坐标系统

    http://tutorials.jenkov.com/svg/svg-coordinate-system.html svg的坐标系统(和大多数计算机绘图的坐标系统)和数学中绘图系统有点不一样 数学/ ...

  2. SVG Drawing Animation - SVG 绘制动画

    一个小实验,探索 SVG 线图动画的使用情况,以前沿的展示形式呈现图形或网站元素的外观,模拟它们的加载.SVG 真的很强大,有许多创造性和可能性,使用 SVG 可以制作各种有趣的网站交互效果.今天这篇 ...

  3. SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  4. SVG 学习<七> SVG的路径——path(1)直线命令、弧线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  5. SVG 学习<六> SVG的transform

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  6. SVG 学习<五> SVG动画

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  7. 使用在线编辑 svg 软件修改 svg 图片

    网站需要使用图标字体,但设计师给的图标大小有问题,故使用下面说陈述方法简单修改了一下.使用到的在线编辑软件地址为:https://editor.method.ac/ 问题: 注:至于如何使用图标字体( ...

  8. 2. svg学习笔记-svg中的坐标系统和viewbox

    我是通过<SVG精髓>这本书学习的svg,说实话,这本书写的不好,或者说翻译的不好,我没有看过这本书的原版,不知道原文写的怎么样,但是翻译出来的有些句子真的很拗口.以前老师给我们API文档 ...

  9. svg图标(svg实现的QQ图标)

    与传统的图片相比,用svg实现的图标要更好控制. 比如.若要改变图标的颜色,如果用图片的话,就需要UI设计人员调整图片,而如果用svg的话,就不用那么麻烦,开发人员改样式就行了. 附一个svg实现的Q ...

随机推荐

  1. kNN(k近邻)算法代码实现

    目标:预测未知数据(或测试数据)X的分类y 批量kNN算法 1.输入一个待预测的X(一维或多维)给训练数据集,计算出训练集X_train中的每一个样本与其的距离 2.找到前k个距离该数据最近的样本-- ...

  2. Caffe2源码解析

    写在前面 上一篇文章对Caffe2中的core模块进行了简单拆解Caffe2源码解析之core,本篇给出其它模块的拆解,目的是大致了解每个模块的内容和目标,进一步理解Caffe2的整体框架.内容不多, ...

  3. 2022年官网下安装MongoDB最全版与官网查阅方法(5.0.6)

    一.下载安装 1.百度搜索,找到官网,或直接访问:https://www.mongodb.com/ 2.寻找下载位置,双击下载. 3.找到本地位置,双击执行,进入欢迎界面,选择next. 4.勾选协议 ...

  4. 详解Nacos 配置中心客户端配置缓存动态更新的源码实现

    Nacos 作为配置中心,当应用程序去访问Nacos动态获取配置源之后,会缓存到本地内存以及磁盘中. 由于Nacos作为动态配置中心,意味着后续配置变更之后需要让所有相关的客户端感知,并更新本地内存! ...

  5. web自动化之selenium(二)

    selenium自动化测试框架 一.什么是自动化测试 利用软件(或者说机器代替人)实现全部或者部分测试任务的过程 二.为什么要进行自动化测试 ​ 自动化测试可以完成许多手工测试无法实现或难以实现的功能 ...

  6. e值计算来了

    e值该如何计算呢? 若关于ex幂级数展开 ex=1+x+x2/2!+x3/3!+•••+xn/n! 取x=1,有e=1+1/2+1/6+••• 接下来就是十分简单的编程 这里选用了python语言(当 ...

  7. Java基础——自动装箱与拆箱

    装箱:把基本数据类型转换为对应的包装类类型 //装箱Integer i=Integer.ValuesOf(100);//自动装箱integer i1=100;//能够直接赋值成功的称为自动装箱,也调用 ...

  8. exit函数和return语句

    exit函数是c语言的库函数,有一个整型的参数,代表进程终止,这个函数需<stdlib.h>头文件 在函数中写return只是代表函数终止了,不管在程序的任何位置调用exit那么进程就立即 ...

  9. ubuntu20 源码安装nginx以及常用命令

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 ubuntu下安装nginx 个人建议还是不要自己apt-get安装,反正最后加模块还是得用源码编译安装那一套流程 下的慢的该换源换源,该换网换网 ...

  10. TransactionScope是什么

    TransactionScope使用说明 TransactionScope是.Net Framework 2.0滞后,新增了一个名称空间.它的用途是为数据库访问提供了一个"轻量级" ...