72

学习了,CSS中内联SVG图片有比Base64更好的形式

 5 years ago
source link: https://www.zhangxinxu.com/wordpress/2018/08/css-svg-background-image-base64-encode/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

这篇文章发布于 2018年08月19日,星期日,19:50,归类于CSS相关,SVG相关。 阅读 93 次, 今日 88 次

byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=7957

本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意。

一、之前SVG背景图的做法

U367vyB.jpg!web

在写这篇文章之前,对于SVG图标或图形,如果作为CSS背景使用,只要尺寸不超过2K,很多时候我都是直接内联在CSS代码中的,采用的形式是base64格式。

例如下面这个截图中的下箭头小图标:

euu2umz.png!web

相关CSS代码如下:

.icon-arrow-down {
    width: 20px; height: 20px;
    background: url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAyMDAgMjAwIj48cGF0aCBmaWxsPSIjMjQ4NmZmIiBkPSJNMTQ1LjY1OSw2OC45NDljLTUuMTAxLTUuMjA4LTEzLjM3Mi01LjIwOC0xOC40NzMsMEw5OS40NzksOTcuMjMzIEw3MS43NzIsNjguOTQ5Yy01LjEtNS4yMDgtMTMuMzcxLTUuMjA4LTE4LjQ3MywwYy01LjA5OSw1LjIwOC01LjA5OSwxMy42NDgsMCwxOC44NTdsNDYuMTgsNDcuMTRsNDYuMTgxLTQ3LjE0IEMxNTAuNzU5LDgyLjU5OCwxNTAuNzU5LDc0LjE1NywxNDUuNjU5LDY4Ljk0OXoiLz48L3N2Zz4NCg==) no-repeat center/100%;
}

实时效果如下:

矢量,少了个文件请求,渲染几乎无延时,自认为性价比不错。

然而,今天我发现,对于SVG图形,使用Base64格式进行内联,并不是最佳的做法,还有更好的实现方式,就是直接使用SVG XML格式代码,无需进行base64转换。

二、SVG直接内联

方法就是把SVG代码直接内联在CSS的 url() 方法中,语法就是 data:image/svg+xml;utf8, 加上完整的SVG代码即可!例如比较常用的 background-imageurl() 方法,代码如下:

.icon-arrow-down {
    width: 20px; height: 20px;
    background: url('data:image/svg+xml;utf8,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><path fill="#00A5E0" d="M145.659,68.949c-5.101-5.208-13.372-5.208-18.473,0L99.479,97.233 L71.772,68.949c-5.1-5.208-13.371-5.208-18.473,0c-5.099,5.208-5.099,13.648,0,18.857l46.18,47.14l46.181-47.14 C150.759,82.598,150.759,74.157,145.659,68.949z"/></svg>') no-repeat center;
    background-size: 100%;
}

您可以狠狠地点击这里: SVG代码直接写在CSS中demo

可以看到在Chrome浏览器下,小箭头图标显示出来了:

u67raqn.png!web

然后,不要高兴地太早,我们打开IE浏览器一看,心凉了半截,一片空白!

vuq2Yrj.png!web

莫非IE浏览器不支持这种表示方法?

大家莫急莫慌且淡定,IE浏览器是支持直接内联的,只是,IE浏览器出于安全考虑,需要对一些字符进行安全转义。

使IE浏览器也支持的处理

首先,我们对所有SVG字符进行URL-encode肯定是OK的,例如执行:

encodeURIComponent('<svg version="1.1" ...</svg>')

得到如下CSS:

.icon-arrow-down {
    width: 20px; height: 20px;
    background: url(data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22200%22%20height%3D%22200%22%20viewBox%3D%220%200%20200%20200%22%3E%3Cpath%20fill%3D%22%2300A5E0%22%20d%3D%22M145.659%2C68.949c-5.101-5.208-13.372-5.208-18.473%2C0L99.479%2C97.233%20L71.772%2C68.949c-5.1-5.208-13.371-5.208-18.473%2C0c-5.099%2C5.208-5.099%2C13.648%2C0%2C18.857l46.18%2C47.14l46.181-47.14%20C150.759%2C82.598%2C150.759%2C74.157%2C145.659%2C68.949z%22%2F%3E%3C%2Fsvg%3E) no-repeat center;
    background-size: 100%;
}

结果IE浏览器下SVG图标出现了(包括IE9浏览器):

jI3q6zZ.png!web

眼见为实,您可以狠狠地点击这里: CSS中SVG代码完全转义demo

但是,完全URL-encode后也会带来另外的问题,和转义前原始SVG相比,可读性差了很多,想改个颜色都找不到在哪里。那有没有可以进一步提升的空间呢?

有!

部分URL encode IE浏览器也兼容

实际上,完全URL encode是没有必要的,也就是,我们无需让所有的字符都encode也能让IE浏览器正确识别。根据前辈的实践,只需要对下面这些字符转义就能满足绝大多数的场景,它们是: "%#{}<>

其中,由于XML中属性值双引号单引号没有区别,因此我们可以改成单引号 ' ,省去转换还增加了可读性,然后 url() 中使用双引号 " 包起来。

于是,下面的CSS加内嵌SVG代码就能在IE浏览器下正常工作:

.icon-arrow-down {
    width: 20px; height: 20px;
    background: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 200 200'%3E%3Cpath fill='%2300A5E0' d='M145.659,68.949c-5.101-5.208-13.372-5.208-18.473,0L99.479,97.233 L71.772,68.949c-5.1-5.208-13.371-5.208-18.473,0c-5.099,5.208-5.099,13.648,0,18.857l46.18,47.14l46.181-47.14 C150.759,82.598,150.759,74.157,145.659,68.949z'/%3E%3C/svg%3E") no-repeat center;
    background-size: 100%;
}

结果IE9+浏览器下SVG背景也能正常显示:

ni6n6vv.png!web

眼见为实,您可以狠狠地点击这里: SVG转义后的代码直接写在CSS显示demo

可以看到,部分转义后的SVG代码既满足的兼容性要求,同时可读性也有了进一步的提高。

例如,我们想改变此SVG图标的颜色,就简单了,直接把 fill='%2300A5E0' 这里的 00A5E0 改成我们希望的十六进制颜色值即可。要是以前的Base64格式,改颜色是不可能的,需要该原始SVG并重新生成一下,特麻烦。

而且,直接原始SVG内嵌,即使有部分转义,其字符大小也明显比Base64格式要小。因此,理论上,CSS中内联SVG背景图,没有使用Base64格式的理由。但,目前大规模使用还有一个阻碍,就是缺少转换的工具,总不可能每次我们都手动修改需要转义的字符吧。

不要担心,工具是会有的,我这就给大家写一个,自带压缩和转义。 Zn6Fn2z.png!web

三、在线SVG压缩和转义工具

z6V3aaZ.jpg!web

哎呀,不容易呀,周五晚周六晚加周日下午这个页面才弄好。

当当当当,隆重介绍下:SVG在线压缩合并工具

AZfQVz3.png!web

支持选择SVG文件上传,支持拖拽上传,也支持直接粘贴SVG代码进行压缩。

例如这个名为download.svg的SVG文件(下载自iconfont.cn),我们上传压缩下,结果有:

u22Uj2q.png!web

其中,左边的多行文本域中是压缩后的SVG代码,右边的文本域中是压缩并转义的SVG代码,可以直接用在CSS代码中,也就是本文介绍的这种内联方式,来,实地测试下,点击文本域右上方的复制图标按钮,复制转义代码,放在CSS中,如下:

.icon-download {
    width: 40px; height: 40px;
    background: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='128' height='128'%3E%3Cdefs%3E%3Cstyle/%3E%3C/defs%3E%3Cpath d='M332.32 464.112l144 160a47.952 47.952 0 0 0 71.36 0l144-160a48 48 0 0 0-71.36-64.224L560 466.912V176a48 48 0 1 0-96 0v290.912l-60.32-67.024a48 48 0 1 0-71.36 64.224zM880 560a48 48 0 0 0-48 48v192H192V608a48 48 0 1 0-96 0v240a48 48 0 0 0 48 48h736a48 48 0 0 0 48-48V608a48 48 0 0 0-48-48z'/%3E%3C/svg%3E") no-repeat center/100%;
}

效果棒棒哒!

本工具还支持实时SVG Sprites合并,有时候一些小项目不想搭笨重的Node任务流,就可以试试这个敏捷轻便在线小工具。 emURJjj.png!web

四、结束语

这篇文章从周一写到周日,大部分时间就在产出最后那个SVG在线压缩工具上,压缩底层使用的是著名的SVG优化工具svgo(万级别Star项目,很强),所以压缩的质量大家不用担心。

工具页面还有个设置按钮,点击会展开参数配置列表,可以对几十个优化参数进行配置,按钮位置参见下图:

AjmAf2v.png!web

感谢LuLu UI提供UI界面支持,另外点击按钮直接下载SVG文件是纯前端实现的,有兴趣可以参考这篇文章:“ JS前端创建html或json文件并浏览器导出下载 ”。

最后,对本文内容总结下:CSS中内联SVG的时候,没有使用Base64格式的任何理由,请使用部分转义的SVG原始代码代替,如何得到转义SVG代码,可以使用这个SVG在线压缩合并工具。

哦,对了,好像微信小程序中Base64的SVG背景并不支持,但是直接SVG原始代码是支持的。

以上~

感谢阅读,欢迎交流与反馈!

IzmQRff.png!web

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。

本文地址: https://www.zhangxinxu.com/wordpress/?p=7957

(本篇完)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK