共计 6092 个字符,预计需要花费 16 分钟才能阅读完成。
图标是页面中十分敌对的附加物,许多网站都会应用各种图标来丑化页面款式,给用户提供更好的指引。本文将会和大家一起学习页面图标的发展史,以及以后的最优解决方案。
- 传统图标
- 字体图标
- SVG 图标
传统图标
编写图标最简略的形式就是应用一张图片,如:
<html>
<body>
图标 <img src="xxx.png" />
</body>
</html>
我在刚开始写页面的时候就是这样做的,感觉 so easy,直到业务变得越来越简单,我就不得不思考以下几个问题:
- 图标须要适配多个客户端
- 图标太多须要优化
- 图标须要动静批改色彩
对于适配多个客户端的问题,设计师们通常都会给咱们提供多个尺寸的设计图(@1x 图、@2x 图),于是咱们就能够依据不同的客户端来抉择对应尺寸的图片。
通常应用形式是:媒体类型 或者 配置 srcset。
例如:
<html>
<head>
<style>
/* 应用媒体查问,为每个端适配不同尺寸的图片 */
.@media screen and (max-width: 300px) {
.img {background-image: url("1x.png");
}
}
.@media screen and (max-width: 600px) {
.img {background-image: url("2x.png");
}
}
</style>
</head>
<body>
<!-- srcset 能够让不同的客户端主动匹配适合尺寸的图片 -->
<!-- 如:当设施像素比为 2 时,浏览器会主动抉择 2x 图进行渲染 -->
<img src="1x.png" srcset="1x.png 1x, 2x.png 2x" />
</body>
</html>
通过下面的办法,多客户端适配问题解决了,但咱们应用了多张内容雷同、尺寸不同的图标,这无疑减少了图片的数量。
随着图片的增多,图片治理就是一个问题。每一张图片都会发动一个 HTTP 申请,而浏览器并行加载同一域名下的申请是有限度的,太多的图片无奈全副并行加载,就会进行排队加载,排在前面的图片也就不能及时失去渲染。
通常,解决大量图片 HTTP 申请,有以下两种形式:
- 雪碧图
- Base64 图
雪碧图指的是,将所有小图片合并成一张大图片。在浏览器渲染时,这张大图片只须要发动一次 HTTP 申请,而后就被浏览器缓存起来了,当再次应用该图片时,就会间接从缓存中进行读取,从而防止了发动屡次 HTTP 申请。
首先,咱们须要将许多小图片合成一张大图:
而后在 CSS 中进行定位。
.icon1,
.icon2,
.icon3,
.icon4 {
width: 54px;
height: 54px;
background: url("../ 大图.png");
}
/* 定位背景图,让图片显示到对应的地位 */
.icon1 {background-position: -168px 0px;}
.icon2 {background-position: -56px 0px;}
.icon3 {background-position: 0px 0px;}
.icon4 {background-position: -112px 0px;}
能够看到,应用雪碧图布局时,所有的图片都应用了同一张大图,而后应用背景图去定位,以辨别不同的小图标。
总结一下雪碧图的特点:
- 只需发动一次 HTTP 申请。
- 只能通过 CSS 背景图渲染。
- 如果只用到了大图中的一张小图,也须要加载整张大图,有点浪费资源。
- 不利于保护,每次新增图标时,都不能影响到之前曾经排好的图标,所以生存工具须要更智能。
接下来,咱们看一下 Base64 图:
Base64 图指的是,将一张图片数据编码成一串字符串,并应用该字符串代替图像地址。
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAYAAABIdFAMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNo8zjsOxCAMBFB/KEAUFFR0Cbng3nQPw68ArZdAlOZppPFIBhH5EAB8b+Tlt9MY"
/>
能够看到,图片的 src 并不是一个地址,而是一个字符串,这样甚至能够不发动 HTTP 申请,就能渲染图片。
Base64 的原理是 Data URLs,即:前缀为
data:
协定的 URL,容许开发者向 HTML 中嵌入小文件。
总结一下 Base64 图的特点:
- 无 HTTP 申请。
- 图片内容由字符串示意,通常会很长,这会减少 HTML 的大小。
- Base64 并不是 url,所以不能进行缓存。
- 实用于极小的图片,如:1×1 的小图,用作背景图,反复渲染平铺整个页面。
Ok,咱们来总结一下传统图片渲染图标的几种形式:
最初剩下动静批改图片色彩的问题,这个就比拟难管制了,能够用 CSS Filter 去做滤镜,通过调整图片的含糊度、对比度、灰度、透明度等,间接地扭转图片色彩。
例如:
img {
// 让图片变灰
filter: grayscale(100%);
// 让图片变含糊
filter: blur(5px);
// ...
}
然而 CSS Filter 能批改的色彩是无限的,如果想任意批改图标色彩,咱们持续往下看。
字体图标
随着互联网的一直倒退,字体图标逐步来到了咱们的视线,它能够像解决文字一样去解决图标,大大地进步了图标的灵活性。应用字体图标能够十分轻松地批改图标色彩。
字体图标的应用形式
字体图标应用十分不便,咱们只须要在页面中引入对应的字体文件,而后编写对应的字符就能够了。
字体图标有两种写法:
- 间接编写 Unicode 编码。
- 应用伪类去写 Unicode 编码。
例如:
<html>
<head>
<style>
/* 首先引入字体文件 */
@font-face {
font-family: "iconfont";
src: url("iconfont.eot"), url("iconfont.woff") format("woff"), url("iconfont.ttf")
format("truetype"), url("iconfont.svg#iconfont") format("svg");
}
/* 定义字体类 */
.iconfont {
font-family: "iconfont";
font-size: 16px;
}
/* 在伪类中编写 unicode 字符 */
.icon-edit:before {content: "\e603";}
</style>
</head>
<body>
<!-- 应用 &# + unicode 编码能够渲染对应的字符。-->
间接应用字符编码:<i class="iconfont"></i> 应用类名渲染(将字符写在了伪类中):<i
class="iconfont icon-edit"
style="color:red"
></i>
</body>
</html>
能够看到,有了字体图标后,咱们能够像解决文字一样去批改图标的色彩。
字体图标的原理
字体图标的实质是一种字符,而字体是渲染字符的一种形式,它决定了咱们在键盘上敲打的字符最终在页面上长什么样。
这就好比书法家写字,不同的字体就是不同的书法家,不同的书法家尽管都在写同一个字,然而因为字迹的不同,写进去的文字也就大不相同。
试想一下:有一个特立独行的书法家,他并不依照惯例的写法来写字,他写进去的字都是一个个的小图标,那不就是字体图标了吗 ????。
其实,书法家写字这个情理,在网页中也是一样的。
页面在渲染文字的时候,会先将文字转换为对应的 unicode 编码,而后依据 css 中配置的 @font-face url
找到对应的字体文件(eot ttf woff 等),接下来在该字体文件中找到这个 unicode 编码对应的绘制形状,最初绘制在页面上。
咱们看到的内容 = fontFamily(unicode);
深刻字符编码
在计算机中,咱们能看到的所有字符,底层都是用二进制来示意的,如:空格符在二进制中就是 00100000
,大写的字母 A
在二进制中就是 01000001
。
为了不便保护字符和二进制的关系,前辈们将这些对应关系记录成一张表,如:
ID | 字符 | 二进制 |
---|---|---|
32 | 空格符 | 00100000 |
65 | A | 01000001 |
这个表就是咱们常说的字符编码,上表即 ASCII 编码的一部分。
最后的 ASCII 编码只能示意 128 个符号,次要存储的是 26 个英文字母的大小写和数字等。有了 ASCII 编码后,咱们就能编写对应的字体去渲染表中的字符了,但其余没有被记录的符号也就无奈显示了,如:不同国家的汉字、emoji 符号等。
为了解决中文字符编码问题,国家制订了 GB2312 编码,该编码收录了 6763 个汉字,涵盖了中国大陆 99.75% 的应用频率,能满足绝大多数的汉字需要。
但 GB2312 编码只实用于中文,而世界上还有 200 多个国家,他们也有本人独特的文字,难道每一个国家都须要自制一套字符编码吗?
其实不必,在 1991 年 10 月,诞生了 unicode 编码,它制订了一套对立的编码标准,收纳了世界上所有国家的文字符号,到目前为止,曾经有 100 多万个符号。
unicode 最多 4 个字节,一个字节 8 个比特位(示意二进制中的 0 或 1),也就是
2**32
个状态,齐全能够包容世界上所有的符号。
所以,任何一个符号,都能够在 unicode 编码中被找到。
总结一下字体图标的特点:
- 字体图标是矢量图,即便放大也不会变含糊。
- 字体图标能够通过 CSS 款式进行管制,应用更加灵便。
- 字体文件个别比拟大,但能够将不必的字体删掉。删除字体中没有用到的汉字
最初,字体图标虽好,但它的实质依然一种文字,所以 CSS 在设置 color 时只能选一种色彩,如果咱们想制作一个多色的小图标,也就无能为力了。
SVG 图标
SVG 诞生于 1999 年,目标是用来绘制矢量图形,它次要通过定义必要的线和形态来创立一个图形。
SVG 图标应用形式
SVG 采纳 XML 格局的语法来画图,例如:
<html>
<head>
<style>
.my-style {
/* 管制填充色 */
fill: red;
}
.my-style use {color: orange;}
</style>
</head>
<body>
<svg style="display: none;">
<symbol viewBox="0 0 24 24" id="heart">
<path
d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z"
></path>
</symbol>
</svg>
<svg class="my-style">
<use xlink:href="#heart" />
</svg>
</body>
</html>
能够看到,首先咱们把须要应用的图标封装到 symbol 标签中,在应用时只须要 use 一下就能够了。这跟咱们定义一个 CSS class 而后再去 HTML 中援用是一个情理。
如果是用封装好的 SVG 库就更简略了,SVG 库会把所有用到的图标封装到一个 JS 文件中,咱们只须要引入这个 JS 文件,而后就能间接 use 对应的图标了。
咱们再看一个多色 icon 的例子:
<html>
<head>
<style>
/* svg 中的元素存在于 shadom 中,能够通过自定义变量传递参数 */
.icon {
width: 100px;
height: 100px;
margin-right: 10px;
}
.icon--fill {fill: grey;}
.icon--color {
fill: #ef5b49;
--handle-color: #c13127;
--cup-color: #ef5b49;
--smoke-color: #cacaea;
}
.icon--color-alt {
fill: #2f3fff;
--handle-color: #1f2bac;
--cup-color: #2f3fff;
--smoke-color: #a5acbd;
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" class="hidden">
<symbol id="icon-coffee" viewBox="0 0 20 20">
<title>icon-coffee</title>
<!-- 应用自定义变量 -->
<path
fill="var(--handle-color)"
d="M15,17H14V9h3a3,3,0,0,1,3,3h0A5,5,0,0,1,15,17Zm1-6v3.83A3,3,0,0,0,18,12a1,1,0,0,0-1-1Z"
/>
<rect
fill="var(--cup-color)"
x="1"
y="7"
width="15"
height="12"
rx="3"
ry="3"
/>
<path
fill="var(--smoke-color)"
d="M7.07,5.42a5.45,5.45,0,0,1,0-4.85,1,1,0,0,1,1.79.89,3.44,3.44,0,0,0,0,3.06,1,1,0,0,1-1.79.89Z"
/>
<path
fill="var(--smoke-color)"
d="M3.07,5.42a5.45,5.45,0,0,1,0-4.85,1,1,0,0,1,1.79.89,3.44,3.44,0,0,0,0,3.06,1,1,0,1,1-1.79.89Z"
/>
<path
fill="var(--smoke-color)"
d="M11.07,5.42a5.45,5.45,0,0,1,0-4.85,1,1,0,0,1,1.79.89,3.44,3.44,0,0,0,0,3.06,1,1,0,1,1-1.79.89Z"
/>
</symbol>
</svg>
应用
<svg class="icon icon--color" aria-hidden="true">
<use xlink:href="#icon-coffee" href="#icon-coffee" />
</svg>
</body>
</html>
能够看到,SVG 和 HTML 一样具备树形构造,构造中的 path 都是图形中的一个区域,这些区域能够被 CSS 选择器匹配到。当咱们匹配到对应的区域时,就能进行对应的色彩批改了,一张多色的 SVG 图就做好了。案例
总结一下 SVG 图标的特点:
- 反对动静批改多个区域的色彩
- 反对渐变色
- 矢量图,放大也不会变含糊
思考与总结
本文介绍了 3 种小图标的应用形式,这里做一个简略回顾。
- 传统图标,简略粗犷,切好图就能用,但需思考不同尺寸以兼容不同设施,图片的色彩不好更改。
- 字体图标,须要引入字体文件,而后编写特定的字符就能够了,能够很不便的批改色彩,但只能是单色。
- SVG 图标,须要引入写好图标的 SVG 文件,而后讲具体的图标 use 进去即可,能够别离定义图标中不同部位的色彩。
总体来说,3 种图标应用起来都很简略,大家视状况来定吧。