一、CSS内联 SVG
一直觉得 内联 SVG 是 HTML 的延伸,但是内联 SVG 往往会造成HTML结构的臃肿。于是笔者尝试着把 SVG 移植到 CSS 中,如下:
1 | background: url( |
目前(2017.01.12)而言,没有任何浏览器的 CSS 支持内联 SVG 代码,所以上述的代码是一段非法的 css。尽管任何浏览器的 CSS 都不支持内联 SVG 代码,但是所有的现代浏览都是支持内联 SVG 文件,如下:
1 | background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NTAgNDAwIj4gCQkJPHBhdGggZD0iTTAsMCBMNzUwLDAgTDc1MCw0MDAgTDM4OCw0MDAgTDM3NSwzODcsIEwzNjIsNDAwIEwwLDQwMFoiIGZpbGw9IiMwZjAiPjwvcGF0aD4gCQk8L3N2Zz4=); |
内联 SVG 文件即 Data-URI。
二、Data-URI 简介
A new URL scheme, “data”, is defined. It allows inclusion of small data items as “immediate” data, as if it had been included externally.
摘录自:https://tools.ietf.org/html/rfc2397
简单地说,Data-URI 是一种将小文件转换成直接字面数据的方案(scheme)。Data-URI 的语法如下:
1 | data:[<media type>][;base64],<data> |
<media type>
: 即指定嵌入数据的 MIME,对于 PNG 的图片,其格式是:image/png,如果没有指定,默认是:text/plain;[;base64]
: base64 编码扩展,非必选项。如果没指定 base64 编码扩展,后面的 <data>
将使用 URL
编码(即百分号编码)。<data>
: 编码后的小文件数据。图片文件则是对二进制文件流进行编码,文本文件则是对文本进行编码。
附注:Data-URI 是正式术语,日常中更常用的名字是 Base64。
三、sass-svg
sass-svg
是一个将 SVG 代码转化为 Data-URI 的 Sass 库。
了解 Data-URI 后,sass-svg 的作用其实就是把 SVG 进行编码的过程。
1. URL编码
在 JS
中可以使用 encodeURI
或 encodeURIComponent
来对字符进行 URL 编码,而 Sass 并没有相对就的编码方法。
了解一下 URL编码的知识点:
- URL 编码的原理:ASCII 字符 = % + 两位 ASCII 码(十六进制)。例如,字符 a 对应的 ASCII 码为
0x61
,那么 URL 编码后得到%61
。 - 「rfc3986」规定 URL 只允许英文字母(
a-zA-Z
)、数字(0-9
)、-_.~4
个特殊字符以及保留字符(! * ' ( ) ; : @ & = + $ , / ? # [ ]
)。
尽管 Sass 不提供获取 ASCII 码的函数,但创建一张 ASCII 字符 与 ASCII 码 的对照表(map) 却是廉价的。标准的 ASCII 字符一共是 128 个,剔除 rfc3986 规定的不需要编码的字符(84个),再把扣除一些控制符,实际上需要编码的字符只有 13 个,如下:
1 | // ascii 与 16进制对照表 |
实现 URL 编码要求 sass 版本3.3以上,因为需要用到三个内置函数:str_index
、str_slice
和 str_insert
。 实现 URL 编码的过程不详述,笔者已经将相关代码放到 GIT 仓库,有兴趣的同学可以访问 「sass-svg」。
注意:本文所描述的编码仅针对 US-ASCII 字符集。中文或其它字符不讨论
2. Base64 编码
Base64 使用 US-ASCII 子集的64个字符,即大小写的26个英文字母,0~9,+,/。如下:
1 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
Base64 编码总是基于3个字符,每个字符用8位二进制表示,因此一共24位,再分为4四组,每组6位表示一个 Base64 的值。如果不足3个字符,仍将每个字符对应的二进制串起,再按每组6位表示一个 Base64的值,不足6位的用 0
补全,最后生成的 Base64 码不足4位用=
补全。
举个例子来感受一下:
与 URL编码相似,SASS 无法直接获取 ASCII 字符对应的二进制,也无法将6位二进制转成 Base64 码。这意味着需要手动创建两张对照表(map)。如下:
1 | // ascii字符 与 8位二进制 对照表 |
1 | // 二进制 与 base64 对照表 |
实现过程不详述。有兴趣可以访问「sass-svg」。
3. sass-svg 的一个实例
开头的非法 CSS,通过 sass-svg
可以改写成:
1 | // scss |
通过编译最终会生成:
1 | background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOTMuOTY5IDI4LjIxOSI+IAkJICA8cGF0aCBkPSJNMC45NjksMTEuMzEzIEMtMjAuMjA3LDY5LjcxMSAzMTQuMTgzLC00Ny45ODQgMzkzLjk2OSwyNC4zMTIgIi8+IAkJPC9zdmc+"); |
结语
感谢阅读本文。关于 sass-svg
的应用,笔者会有后续文章介绍,如果喜欢本文请关注一下我们『凹凸实验室』的微信公众号:AOTULabs
参考资料
- Data URI scheme - Wikipedia
- RFC 2397 - The “data” URL scheme
- Uniform Resource Identifier (URI): Generic Syntax
- Uniform Resource Locators (URL)
- Base64编码解码算法
- Module: Sass::Script::Functions
- URL编码与解码原理
- Base64编码解码算法