图标字体 VS 雪碧图——图标字体应用实践
2017/04/05 · HTML5 · 1 评论 · 图标字体
原文出处: 人人网FED博客
本文介绍使用图标字体和SVG取代雪碧图的方法。雪碧图是很多网站经常用到的一种技术,但是它有缺点:高清屏会模糊、无法动态变化如hover时候反色。而使用图标字体可以完美解决上述问题,同时具备兼容性好,生成的文件小等优点。
把UI图里的小图标制作成icon font,uiicon
一个交互比较多的UI图里面可能会有很多小图标,一般可用sprites图将多个小图标弄成一张大图,或者其它的办法,各种方法的比较可参见博主的另外一篇博客使用css3新属性clip-path制作小图标,本文深入讨论使用icon-font的的制作方法:在PS里面导出svg,制作字体图标。这种方法既有sprites图不需要浏览器发多次请求的优点,也有使用clip-path/svg矢量无损的优点,并且支持IE6及以上。
使用sprites图可以自行用PS将多个小图标放至一张图:
sprites图的缺点是不是矢量的,在适配布局里,在伸缩时可能会失真。而使用icon fonts是矢量放大无损的。
接下来介绍制作icon fonts的方法。
1. 需要安装PS、AI
2. 下载一个PS的脚本:PSD to SVG,按照里面说明的办法,将脚本放到PS的脚本目录:Adobe Photoshop/presets/scripts,重启PS。
3. 将图层里面的icon形状图层复制到一个新文档,并将图层重命名为.svg后缀结尾。弄成svg结尾主要是为了脚本识别哪些图层要进行转换。注意图层命名最好用字母数字和下划线,不然可能会出问题。
4. 执行文件->脚本->PSD to SVG脚本,可能会提示没有保存文档,所以执行前先把新建的图层保存为一个文件。
6. 执行完脚本后会在psd所在的目录生成两个文件,一个svg和一个ai
7. 用AI打开生成的ai文件,发现只有左下角有一个点显示出来了,如下图左显示,当把鼠标放上去的时候发现那些path是存在的,只是没显示出来。
8. 所以在AI里面把它填充一下,把显示出来的部份填充成黑色,然后另存为svg:File->script->saveDocs as Svg
9. 接下来,借助icomoon,制作字体。打开icommon(如果打不开,得使用代理因为这网站使用了谷歌的一些服务),点击右上角的Import Icon按钮,导入上面保存的svg文件。
icomoon就会跳到select页面,选中刚刚导入的图标:
再点击右下角的Generate Font:
跳到了生成好的icon页面,点击get code:
观察它的使用代码,发现这个图标被拆成了6个span表示6个path,还要调节它们的间距。这不是想要的结果,理想的结果应该是只要一个span表示这个图标就好了。
根据icomoon的给出的提示:
To avoid multicolor glyphs, reimport your SVG after changing all its colors to the same color.
发现是由于各个部份的颜色不一致导致的,上面设置没有显示出来的其它5个部份和已经显示出来左下角那个点的颜色不一致,于是把它们调成一样的。
这里使用linkscape进行编辑,因为linkscape可以直接编辑svg源代码,更加直观,打开用PS生成的还没改过的svg文件:
可以看到,之所以会没显示出来,是因为fill属性设置成了none,所以把它们都改成和左下角那个都一样的颜色:
保存后上传到icomoon,再点get code,生成的字体就是完整的一个实体了:
下载后打开,生成的字体文件放在了fonts目录下,同时icomoon提供了demo,使用时,通过一个@font-face导入字体文件:
@font-face {
font-family: 'icomoon';
src:url('fonts/icomoon.eot?3hb5tb');
src:url('fonts/icomoon.eot?3hb5tb#iefix') format('embedded-opentype'), /*为了支持低版本的IE*/
url('fonts/icomoon.ttf?3hb5tb') format('truetype'),
url('fonts/icomoon.woff?3hb5tb') format('woff'),
url('fonts/icomoon.svg?3hb5tb#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
如果不需要支持ie8及以下,可以像上面的示例一样用一个before或者after的伪类,如果需要的话,就在html文件里面用实体代码吧,例如上面的菜单按钮是:

当然也可以用icommon提供的大量免费的图标和搜索功能,但是使用这些图标的缺点是大小可能是不一致的,导致在UI里面原本相同大小的字体图标需要设置不同的的字体大小。而使用UI图制作的svg大小比例就会贴近UI图,无需设置多个font-size。
需要注意的是,如果以后还要再导入新的图标,需要在原先的基础上添加,icommon支持导入project,将上面的下载的包里面的selection.json导入即可。如果把之前的icon和新的icon再导入一次,会导致之前的icon的编码发生变化。
上面使用了用AI/linscape的方法修正PS导出的ai/svg文件,也可以直接用文本编辑器修改svg文件。
有的时候,可能需要手动调整下svg的结构,例如上面的搜索框,在PS里面设计师是画了两个圆和一条线,如下面所示:
<svg version="1.1" width="40.004px" height="40.004px" viewBox="0 0 40.004 40.004" style="enable-background:new 0 0 40.004 40.004;"
xml:space="preserve">
<!-- 外面的圆 -->
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#505050;" d="M19,0c10.493,0,19,8.507,19,19s-8.507,19-19,19S0,29.493,0,19
S8.507,0,19,0z"/>
<!-- 里面的圆 -->
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#505050;" d="M19,2c9.389,0,17,7.611,17,17s-7.611,17-17,17S2,28.389,2,19
S9.611,2,19,2z"/>
<!-- 放大镜的手柄 -->
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#505050;" d="M32.691,31.287l7.022,7.022c0.388,0.388,0.388,1.017,0,1.404
s-1.017,0.388-1.404,0l-7.022-7.022c-0.388-0.388-0.388-1.016,0-1.404C31.674,30.899,32.303,30.899,32.691,31.287z"/>
</svg>
如果两个圆的fill颜色都设置成一样的灰色的话,那么生成的文件是这样的:
里面那个圆的fill属性的作用导致放大镜中间被填充了,因此需要手动改一下,将两个圆放到同一个path,这样围起来的路径就是一个环:
<svg width="40.004px" height="40.004px" viewBox="0 0 40.004 40.004" style="enable-background:new 0 0 40.004 40.004;"
xml:space="preserve">
<!-- 把两个圆放到一起形成一条封闭的路径,即一个环 -->
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#505050;" d="M19,0c10.493,0,19,8.507,19,19s-8.507,19-19,19S0,29.493,0,19
S8.507,0,19,0
M19,2c9.389,0,17,7.611,17,17s-7.611,17-17,17S2,28.389,2,19
S9.611,2,19,2z"/>
<!-- 放大镜的手柄 -->
<path style="fill-rule:evenodd;clip-rule:evenodd;fill:#505050;" d="M32.691,31.287l7.022,7.022c0.388,0.388,0.388,1.017,0,1.404
s-1.017,0.388-1.404,0l-7.022-7.022c-0.388-0.388-0.388-1.016,0-1.404C31.674,30.899,32.303,30.899,32.691,31.287z"/>
</svg>
生成的放大镜就正常了:
还有的图标可能是由多个图层组成的,这个时候需要分别生成svg,然后放到一起,用Inkscape或ai调下相对位置。这里需要点svg的知识,可以参考MDN上的svg教程。
最后再比较下大小,把上面第一张sprites图里面的9个小图标都制作成icon fonts,生成的文件大小为:
最大的为6.6KB,小的为2.6KB,而上面生成的sprites图为7.1KB,用tinypng压缩后为3.0KB。可以看到,如果只有几个图标并且图标本身就比较小时,在文件大小上,icon-font比sprites图的优势并不明显。当图标增加到18个,即把上面的图标再导入一次,现制作的icon-fonts大小为:
18个icon-font的最大svg格式的为13kb,最小的为4.1KB,sprites图为6KB,考虑到svg格式的并不太会可能被浏览器下载, 如下图所示。所以在文件大小上,icon-fonts还是比sprites图有优势的,如果图标个数不多的话差别不大。如果图标需要展示得很大的话,icon fonts的优势就很明显了。
IE6 | 仅支持 Embedded OpenType(.eot) 格式。 |
IE7 | 仅支持 Embedded OpenType(.eot) 格式。 |
IE8 | 仅支持 Embedded OpenType(.eot) 格式。 |
Firefox 3.5 | 支持 TrueType、OpenType(.ttf, .otf) 格式。 |
Firefox 3.6 | 支持 TrueType、OpenType(.ttf, .otf) 及 WOFF 格式。 |
Chrome | 支持 TrueType、OpenType(.ttf, .otf) 及 SVG Font(.svg) 格式。 |
Safari | 支持 TrueType、OpenType(.ttf, .otf) 及 SVG Font(.svg) 格式。 |
Opera | 支持 TrueType、OpenType(.ttf, .otf) 及 SVG Font(.svg) 格式。 |
来自w3 help
使用sprites图的另外一个缺点是,在移动端低配置的设备,可能会给内存和CPU带来很大的压力,如果sprites图太大的话。而icon font的最大优点是矢量无损,缺点是只能支持单色的图标,因为它是一个普通的字体,还有在制作上稍麻烦。
参考:
1. 使用css3新属性clip-path制作小图标
2. icomoon,制作icon font的在线工具
3. PSD to SVG
font,uiicon 一个交互比较多的UI图里面可能会有很多小图标,一般可用sprites图将多个小图标弄成一张大图,或者...
一.iconfont使用场景(优缺点);
一般我们项目决定要使用一个技术点前,会查相关资料对其有大概的理解。例如, 这次要使用iconfont实现功能, 理解相关资料后归纳、总结出它的优、缺点以及它的使用场景。
图标字体优、缺点:
1.优点;
轻量(文件体积小)、灵活(样式可改变图标)、兼容性好(IE8+)。
2.缺点;
图标只能单色调(太复杂的多色图标无法实现)、生成图标字体相对花时间。
跟webfont一样iconfont实现的关键代码是“@font-face”(细谈CSS@font face)查看其浏览器兼容信息为IE8+:
@font-face兼容
低版本浏览器其实也有方法兼容,icoMoon是图标字体开发时生成字体文件及demo的网站,用过icoMoon的同学都知道其有一个“Support IE 7”选项, icoMoon IE7支持实现原理:样式上用*zoom 触发重绘(触发haslayout), 脚本上检测 关键字className动态插入dom节点实现;考虑到IE7目前的市场份额,以及该方式带来的性能消耗,本人不建议去兼容。
另外,图标只能单色调这个问题也有办法解决,阿里巴巴iconfont+ 也是图标字体开发时生成字体文件及demo的网站;阿里巴巴iconfont+ 生成的demo可以解决图标单色调问题,其原理是 生成svg合集, 然后使用svg呈现图标。但该方式兼容性较差(SVG兼容小结), 如是移动端开发不考虑低版本浏览器兼容问题可以尝试该方式。
根据以上图标字体的优缺点, 个人总结的使用场景如下:
1.web app(H5) 小图标 放大失真问题解决;
移动页面大多数情况没办法用雪碧图,用了雪碧图表示图片大小固定了,而移动端需要兼容不同屏幕大小的移动设备,这就需要图片是可以根据屏幕尺寸而改变的。 如果你的图尺寸是固定的,那就可以用雪碧图。
2.PC端小图标性能更佳、小图标尺寸修改不用改原图;
PC端页面优化,可将部分雪碧图换成小图标,字体图标比雪碧图的http请求少、体积小;(加载一个页面时分模块开发关系可能有多张雪碧图,但使用字体图标,文件一个就够)
PC端做换肤业务时,使用了字体图标实现起来更加的优雅、方便。(之前做页面换皮肤功能时发现换肤时小图标得多出一套雪碧图略麻烦, 如果是字体图标直接更新颜色样式就OK)
知乎、斗鱼、Bilibili这类网站不少地方使用了雪碧图,如果我们维护这类网站,能用图标字体替换么?
从两方面考虑:
1.开发时间成本问题, 使用自定义图标字体替换雪碧图需要一定时间,如果要求快速更新小图标建议维持用雪碧图;
2.字体小图标兼容、单调色问题, 如果网站需要兼容低版本浏览器、且图标复杂、或者多色那还是得用雪碧图。
B站
知乎
斗鱼
所以实现小图标时雪碧图 跟 图标字体会在一个网站共存,自定义图标字体 为什么比较耗时,且太复杂图标无法实现?请往下看iconfont开发流程就了解了。
注意这里,不是使用基本形状,而是使用了svg里的path,贝塞尔曲线,也就是PS/AI里面的钢笔工具,在d里面定义路径是如何移动和弯曲的。绘出的形状要放在clipPath标签里,给这个clipPath添加一个id,在下面的CSS里将会使用到,同时设置clipPathUnits为objectBoundingBox,作用是将单位设置成比例[0,1],这样就可以适配出不同大小的形状。clipPathUnits有两个取值,另外一个取值是userSpaceOnUse,是默认值,一般单位为px。
坑3:生成的SVG填充可能被置为none
有时候会遇到生成了svg,但是上传上去是空的,检查一下svg文件发现是fill被置为none了,如下所示:
生成的svg是fill:none
这个时候需要手动改一下svg文件,把fill:none改成随便一个色值即可,如fill:#000000.
二.iconfont开发流程;
接下来就是本文篇幅最大的章节, 我将从自己实现图标字体小demo上详细的列出所有步骤。
使用免费图标字体:
如果网站使用的不是自定义的图标字体,而是网上开源的免费图标那实现上将非常的简单;
例如, 我要使用阿里巴巴iconfont+ 上的图标字体, 进入网站并登陆(可以用github账号登录),从图标库选取自己喜欢的图标:
iconfont+
这里我选取了三个小图标,点击右上角购物车,将选取的图标添加到新建项目,然后点选“下载至本地”:
iconfont+_2
下载下来的压缩包就包括了 三小图标字体文件, 以及三种实现方式的demo;
下载目录
下载图标字体的三种用法,打开对应html(demo_fontclass.html、demo_symbol.html、demo_unicode.html)文件即可了解(也可直接打开我demo里的这三个文件查看用法,所以用法这里不冗述了);有4个字体文件(EOT/SVG/TTF/WOFF)是为了兼容所有浏览器,因为不同浏览器对字体格式兼容是不一样的:
字体文件兼容
使用自定义图标字体:
实际开发中基本都是使用自定义生成的图标字体,大致步骤如下:
1)使用PS-矩形工具 生成图标;
2)AI软件打开PSD文件,File->Scripts->SaveDocsAsSVG 生成SVG文件;
3)访问阿里巴巴iconfont+(或iconMoon)上传SVG生成字体文件;
PS: 教程雪碧图vs图标字体中多了PS导出AI文件的步骤,经实践PS生成的AI文件打开容易显示空白,且AI软件可直接打开PSD文件,该步骤可省略.
其实生成自定义图标字体一般交给设计部同事完成(可能设计同事是用Sketch而不是PS生成小图标), 因为要了解整个流程细节,所以请教了设计部同事生成自定义图标字体的技巧跟方法; 这里就分享下生成自定义图标字体的具体流程:
首先,下载生成小图标的软件: PS(Photoshop)、AI(Adobe Illustrator);
PS
PS下载地址:mac 版、windows版
AI
AI下载地址:mac
版、windows版
1)使用PS-矩形工具 生成图标;
预计demo功能: 三个小图标:笑脸、黑脸、帽子; 默认显示笑脸+帽子,鼠标hover,变成黑脸+帽子(颜色变绿);
将要实现的小demo将有三个小图标, 接下来就使用PS生成这三个小图标;
无论是用Sketch还是Photoshop绘制小图标的思路都差不多,使用各种基本图形相加相减得到想要的小图标;所以太复杂的图形实现起来会耗时甚至无法实现。(PS矢量小图标制作、Sketch小图标制作技巧)
笑脸PSD:
使用PS新建165px * 124px 图层, 使用 “圆角矩形工具”创建100px*100px的圆(颜色#666):
圆形装
继续用 “圆角矩形工具”绘制小图标的眼睛(为了直观可改成白色):
添加眼睛
ctrl+e(command+e)
合并形状并选择“排除重叠形状”:
合并形状
小图标的嘴巴有点复杂,使用钢笔工具或使用两个圆形相减(“排除重叠形状” )+矩形工具(“与形状区域相交”)生成嘴巴:
形状嘴巴
然后 ctrl+e(command+e)
合并形状并选择“排除重叠形状”生成笑脸:
笑脸完成
黑脸PSD:
与笑脸PSD一样流程, 只把嘴巴旋转180度就行:
黑脸
帽子PSD:
使用PS新建165px * 124px 图层, 使用
“椭圆工具”创建150px20px的椭圆(颜色#666),然后画一个90px110px的椭圆:
双椭圆
在第二个椭圆图层使用矩形工具(“减去顶层形状”)删减该椭圆内容然后与第一个椭圆
ctrl+e(command+e)
合并形状:
帽子生成
2)AI软件打开PSD文件,File->Scripts->SaveDocsAsSVG 生成SVG文件;
生成三个小图标的PSD后,我们使用AI软件打开三个文件, 然后分别处理生成SVG文件:
存储为SVG
svg
3)访问阿里巴巴iconfont+(或iconMoon)上传SVG生成字体文件;
将上述步骤生成的SVG文件在阿里巴巴iconfont+中上传,然后这几个小图标就在“我上传的icon”中:
上传
拖拽文件
提交
我的icon
将图标添加入库, 然后添加到项目, 最后就能下载字体及demo到本地了:
添加入库
加入项目
准备下载
字体文件下载好后, 就能轻松实现我的小demo:
小demo
小demo演示地址;
一般一个网页上面,或多或少都会用到一些小图标,展示这些小图标的方法有很多种。最简单的做法就是将UI图上面的每个小图标都保存为图片,一个小图标就一张图片。但这也是比较笨的方法,因为浏览器同一时间最多加载的资源是有限的,例如IE7是2个,IE8是6个,chrome是6个,火狐是8个。如果网页上面有很多张零碎的小图片,导致请求的次数太多,等待加载状态中的资源会很多,明显影响性能。因此,一个改进的办法是使用sprites图,将多张小图放在一张大图,然后限定展示区域的大小,同时改变图片的显示位置background-position来显示不同的图标,游戏里面经常使用这种技术,大大减少浏览器请求的次数。淘宝网就使用这种技术:
雪碧图
雪碧图实例:淘宝PC端
将多张小图放至一张大图
使用的时候,通过background-position调整显示的位置,如下图所示:
雪碧图的使用方法
使用雪碧图唯一的优点,可以说就是减少浏览器的请求次数。因为浏览器同一时间能够加载的资源数是一定的,IE 8是6个,Chrome是6个,Firefox是8个。为了验证,写了以下html结构:(这部份虽然有点跑题,但是很要必要深究一下)
验证Chrome同时加载个数的html–很多张很大的图片
然后在Chrome的开发者工具里面的Timeline可以看到Chrome确实是6个6个加载的,每次最多加载6个:
Chrome同时最多加载资源数为6个
雪碧图的制作方法可以用node的一个的包css-sprite,十分地方便。只要将图标做好,放到相应的文件夹里面,写好配置文件运行,就能够生成相应的图片和css,无需自己手动去调整位置等css属性。详见css-sprite
然而,使用雪碧图存在不可避免的缺点
之前写了一篇关于雪碧图的博文, 评论里有说用http2、或用SVG也有说用图标字体代替,大家知识面是挺广,但深入了解技术点的似乎却不多,否则不会有雪碧图过时无用,用http2或图标字体取代就好了的想法;http2后续有时间再写一篇个人实践、理解博文, 本文主要讲图标字体(iconfont)技术点,从实践开发角度讲述个人对图标字体的理解。
高清屏会失真
在2x的设备像素比的屏幕上例如mac,如果要达到和文字一样的清晰度,图片的宽度需要实际显示大小的两倍,否则看起来会比较模糊:读者可以对比左边文字和右边图片里文字的清晰度
右边图片里的文字比左边字体的文字模糊
特别是现在手机绝大部份是高清屏了,例如iphone 6 plus的分辨率达到了1920 * 1080,所以为了高清屏,使用雪碧图可能要准备多种规格的图片。
本来可以使用svg和clip-path做为h5开发,但是考虑到安卓上的某些国内浏览器不支持,以及safari让人头疼的渲染问题,所以就目前的情况来说应用到生产环境仍不太乐观。所以在PC的web端使用sprites图,在移动的h5端使用icon font并灵活结合其它方法。
结合使用SVG
对于多色的图标,可以在页面插入一个SVG:
左边的location的图标就是使用了svg,效果比直接贴一张PNG好很多
SVG的兼容性,除了IE 8不支持,其它的都还好。况且现在很多新项目都不再兼容IE 8了,不然连个border-radius都用不了。
有几种使用SVG的方法:
- 直接copy到页面
例如,后端如果用的是JSP,那么可以借助include功能:
JavaScript
<%@ include file="loc-svg.jsp"%>
1
|
<%@ include file="loc-svg.jsp"%>
|
loc-svg.jsp里面的内容就是svg:
借助jsp嵌套svg
这样做的缺点是浏览器没办法缓存,同时会阻碍页面的加载。优点是由于是内联的,可以直接用CSS控制svg的样式
- 使用embed/object
XHTML
<embed src="loc.svg" width="100" height="200"/>
1
|
<embed src="loc.svg" width="100" height="200"/>
|
除此之外,还可以使用img标签,将svg的路径作为src属性,这种方法的缺点是没办法用CSS控制样式。还可以转化为base64的方式。更多使用SVG的方式参见:Using SVG
当小个的SVG过多的时候,可能要考虑把多个小的SVG合并成一个SVG,就像雪碧图那样:
- 合并SVG
如下所示:通过一个个的symbol,将多个svg合在了一起,同时将每个symbol svg定义一个id,使用的时候会用到
XHTML
<svg> <symbol viewBox="0 0 101.5 57.9" id="active-triangle"><path fill="#15c0f1" d="M100.4.5L50.7 57.1 1.1.5h99.3z"/> <symbol viewBox="0 0 101.5 57.9" id="logo"><path fill="#15c0f1" d="M120.4.5L50.7 57.1 1.1.5h99.3z"/> </svg>
1
2
3
4
|
<svg>
<symbol viewBox="0 0 101.5 57.9" id="active-triangle"><path fill="#15c0f1" d="M100.4.5L50.7 57.1 1.1.5h99.3z"/>
<symbol viewBox="0 0 101.5 57.9" id="logo"><path fill="#15c0f1" d="M120.4.5L50.7 57.1 1.1.5h99.3z"/>
</svg>
|
使用的时候通过外链的办法将svg引到页面上,如要用到上面定义的logo,通过“文件名#ID”的方式:
XHTML
<svg viewBox="0 0 100 100"> <use xlink:href="icon.svg#logo"></use> </svg>
1
2
3
|
<svg viewBox="0 0 100 100">
<use xlink:href="icon.svg#logo"></use>
</svg>
|
然而蛋疼的IE不支持外链,但是有人写了个插件,可以让IE支持,原理是检测到浏览器不支持外链的时候就将其外链替换成相应的svg内容,详见svg for everybody
使用SVG的还有highCharts和d3.js等。
至此,整个流程说明完毕~ 图标字体和SVG结合使用,提升网站的高清体验。
1 赞 2 收藏 1 评论
三.iconfont实践注意事项.
1.生成图标字体注意事项;
生成图标注意点
截图来自阿里巴巴iconfont+;
更多生成图标字体注意点,请阅读参考资料中《雪碧图vs图标字体》->如何制作图标字体;
2.使用图标字体注意事项;
跨域问题
1)配置自己的服务器;
# For Apache
<FilesMatch ".(eot|ttf|otf|woff)">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
# For nginx
location ~* .(eot|ttf|woff)$ {
add_header Access-Control-Allow-Origin *;
}
2)放在同一个域;
3)使用base64置入CSS中(Icomoon在导出图标时,设置里勾选Encode & Embed Font in CSS选项,IE8+支持base64)。
字体图标出现锯齿的问题
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@font-face与性能问题
1)只在你确定你非常需要 @font-face的时候才使用它;
2)将你的@font-face定义在所有的script标签前;
3)如果你有许多字体文件,考虑将它们分散到几个域名下;
4)不要包含没有使用的 @font-face声明——IE将不分它使用与否,通通加载;
5)Gzip字体文件,同时给它们一个未来的过期头部声明;
6)考虑字体文件的后加载,起码对于IE。
--以上使用图标字体注意事项来源《浅谈图标字体》;
关于字体文件跨域可能是大家最关心的问题, 三种解决跨域的方式中base64至入CSS是比较主流的做法,例如 小米官网 的小图标就是用base64至入CSS中实现。
Icomoon在导出图标时,设置里勾选Encode & Embed Font in CSS选项
目前 Icomoon
勾选生成base64样式会出现收费的问题,那目前实现base64至入CSS有哪些方式呢?
1.使用在线 网站将字体文件 生成base64样式;
百度关键字“图标字体转base64”能找到不少, 这里推荐
转base64在线工具;
在线工具.png
在线工具要求源文件不能大于100K,如果文件过大可以考虑本地构件工具;
2.使用webpack、gulp等构件工具在本地将字体文件转成base64样式;
本demo使用 gulp
base64实现转换:
gulp base64配置
PS: 本demo的“base64”指令 配置的有点粗糙, 如果在生产中会考虑 接受参数 以及 自动将生成的样式合并到 指定样式文件等,大家可以查看 gulp base64官网了解更详细的使用方法。
参考资料:
细谈CSS@font face;
浅谈图标字体;
SVG向下兼容优雅降级技术;
Sketch 绘制小图标技巧;
雪碧图vs图标字体;
PS矢量小图标设计;
本文对应源码:
github源码地址;
demo演示地址;
将图片进行编码,可以使用在线工具base64 image,进行转换。转换之后,你会发现生成的编码特别长,其字节数甚至比原始的照片大,大约大33%。以上面的话筒为例,原始照片为1.3kb,而base64的编码需要1.7kb。同时,另外一个问题是对base64的解析速度比原始二进制的要慢。更严重的一个问题是,如果使用太多的base64,会使得css文件太大,下载和解析的时间较长,导致页面短时间的空白loading状态,效果可能还不如分开使用一张张图片。它的优点是不需要借用额外的图片文件,详细的分析可以看这篇文章。
如何制作图标字体
需要准备PS和AI,打开UI图,选中图标的图层,通常它是设计师画的一个形状:
- 选中图标的图层
然后执行:文件->导出->Illustrator,如下左图所示,将生成一个AI文件。用AI打开刚刚生成的文件,执行File->Scripts->SaveDocsAsSVG,如下右图所示,将生成一个SVG文件:
- 左: PS里导出AI文件,右:AI里面导出SVG
接下来,借助一个第三方的网站制作图标icomoon.io,进入app页面,选择导入icon,将刚刚生成的svg上传上去
- 上传到icomoon
最后生成字体并下载:
- 生成几种规格的字体
使用的时候通过@font-face引入,根据图标的编码就可以在页面中使用了。
然而在实际的操作中并没有像上面说的那么顺利,会遇到很多阻碍,笔者也是摸索了很久才总结了一套实用的经验,这也是其它介绍图标字体的教程没有提及到的,看其它很多教程可能会在实际使用中遇到很多坑。
title
雪碧图的缺点
坑2:有些图标是多个图层组成的
一开始不知道,所以比较笨的方法是分别生成几个svg之后,再去手动去合并svg。其实PS有一个合并形状的功能,选中多个形状后,右键“合并形状”:
使用PS合并多个形状图层
这样就可以了。这篇文章作者作了一个圆形菜单,还有结合css3的动画,作了一些很有趣的动态效果。
雪碧图不方便变化
雪碧图是一张静态的图片,当他生成的那天就注定了他要以什么样的方式展示,因此我不能动态地改变他的颜色,无法让他变大(可能会失真),无法像文字一样加一个阴影效果等等。例如下面的菜单,hover或者选中的时候反色:
选中或者hover时反色
或者是某一天UI要换颜色、某一天老总挂了,为表哀悼,为个公司的网站要换个灰色调。使用雪碧图时,所有的图标都得重新制作。
使用图标字体可以完美解决上面的问题
2. SVG Tutorial,MDN一个关于svg的简明易懂的入门教程。
图标字体icon font
图标字体就是将图标作成一个字体,使用时与普通字体无异,可以设置字号大小、颜色、透明度等等,方便变化,最大优点是拥有字体的矢量无失真特点,同时可以兼容到IE 6。还有一个优点是生成的文件特别小,215个图标的生成的ttf字体文件才41KB
一个图标字体里面的元素
首先,制作一个打勾的svg:
2. 注意缓存
后续加了新的图标字体,如果不做处理的话,已经加载过的浏览器可能会有缓存,导致新的图标字体不会重新下载,所以需要处理这个问题。最简单的就是在上面的@font-face导入的url里面添加一个版本号的参数:
JavaScript
src: url('fonts/icon-font.eot?hadf22');
1
|
src: url('fonts/icon-font.eot?hadf22');
|
或者更彻底的:改变文件名、路径名。
参考:
使用一个脚本自动导出svg
在上面的操作中,都是要先执行PS导出再到AI里面执行导出,其实有一个脚本,能够自动执行这两步:PSD to SVG, 支持PS CS6,不支持CC,还可以把这个脚本设置一个快捷方式,用起来非常方便。使用这个脚本需要注意的是图层的命名不能带中文,不然会出错,所以通常把图层复制到一个新的文件里面进行操作。
使用PSD to SVG增加便利
现在重点说下,图标字体的使用和一些注意事项
但是要看到这种方法也是有缺点的,即内存和CPU的使用增加,对于移动端低内存和CPU的设备来说,可能会有压力。使用sprites图,网上有很多在线的功具可以生成,同时会生成各个小图标的position位置,例如
图标字体的使用
通过font-face导入自定义字体,可以参考字体下载后的demo。然后,把所有使用图标字体的span/a标签都加一个.icon的类,.icon类设置font-family为font-face定义的字体名
JavaScript
@font-face { font-family: 'icon-font'; src: url('fonts/icon-font.eot'); src: url('fonts/icon-font.eot#iefix') format('embedded-opentype'), url('fonts/icon-font.ttf') format('truetype'), url('fonts/icon-font.woff') format('woff'), url('fonts/icon-font.svg#icon-font') format('svg'); font-weight: normal; font-style: normal; } .icon{ font-family: "icon-font": }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@font-face {
font-family: 'icon-font';
src: url('fonts/icon-font.eot');
src: url('fonts/icon-font.eot#iefix') format('embedded-opentype'),
url('fonts/icon-font.ttf') format('truetype'),
url('fonts/icon-font.woff') format('woff'),
url('fonts/icon-font.svg#icon-font') format('svg');
font-weight: normal;
font-style: normal;
}
.icon{
font-family: "icon-font":
}
|
最后,每个图标使用它在相应的编码或者HTML实体:
图标字体的两种使用方法
其中,e9d3是当前图标在这个字体里面的十六进制编码。在普通字体里,0的编码是0x16,即48,为0的ascii编码。
在使用过程中遇到的坑:
.tri{
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
1. webkit浏览器会在加缘加粗1个像素
如下,读者可找下区别:
左边的图标边缘多了一个像素,右边是正常的
这个问题在间距比较小的时候就会比较明显,例如上图第二个图标中间。解决文案是加一个font-smoothing的属性:
CSS
.icon{ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
1
2
3
4
|
.icon{
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
|
3. icomoon和fontello,提供icon-font/svg小图标的网站。
图标字体的缺点
图标字体有一个显而易见的缺点,不支持多色图标。因为它是一个字体,决定了它只能是单色的。如果实再是要使用多色的图标,甚至带一些特殊效果的那就使用SVG吧。
<div class="icon">
</div>
.icon{
width: 100px;
height: 100px;
background: #ff7443;
text-align: center;
background: #ff7443;
border-radius: 100px;
}
.tick{
display: inline-block;
-webkit-clip-path: url(#tick-mask);
clip-path: url(#tick-mask); /* 在这里对白底的span进行剪切 */
width: 90%;
height: 90%;
background: white;
margin-top: 5%;
}
坑1:图标字体只支持单路径
通常情况下,设计师在制作图标的时候是用多个路径组合出来的,在上面的导出的svg也是带有多个路径的,打开svg文件就可以知道,它是由几个path组成的:
导出的svg文件是由几个path组成的
但是字体只支持单路径, 一个解决办法是手办修改svg文件,把多个path合并成一个,这就要求对svg格式比较熟悉。但是这种方法吃力不讨好,只适用比较简单的情况,复杂的图标最后合并的效果很难做到和原先的一模一样。
有一个比较智能的办法,就是使用PS的合并形状组件的功能:
使用PS合并形状组件
这样子生成的svg就是单路径的,有时候会遇到“合并形状组件”的菜单项是置灰的,只要把图层的小眼睛点掉再打开就可以了(或者可能本身就是单路径的)。
使用这种方法的优点是很大程序上减少了图片需要的空间,可以自由改变大小,改变颜色,支持IE6及以上。缺点是只适用于纯色的图标。手机淘宝和百度就使用了这种技术
3. 多人协作
icomoon免费版的数据是存储在浏览器的本地数据库的, 商业版交点钱可以把数据放在云端,从而实现多人协作。免费版也可以实现多人协作,方法是将别人生成的字体svg导进去再添加,生成新的svg字体,同样别人要再上传的时候先上传这个svg。商业版使用的时候需要注意多人同时操作的情况,有可能会同时生成相同的编码。阿里也提供了一个在线的图标字体制作网站:
还有一种办法是使用Unicode字符,Unicode也提供了很多的图标和表情,例如打勾,✔
✓ ☑,使用起来最为简单,可惜的是,不同的字体差别很大,有些字体没有这些符号,甚至是同一个字体在不同的设备上看起来也会有差异,例如✔在安卓机上的形状这是样的(中间的勾),而在ios上是这样的
,同样都是使用了微软雅黑字体。
第二种改进的办法是使用base64的编码方式。将原始二进制的图片编码为base64,然后使用css的background: url(data:image/png;base64,%encoding%)的方式,例如百度的首页搜索栏右边的话筒就是用这样的方式:
上面提及的各种方法都存在一个缺点,没有语义性,都是一个空的span和div,对屏幕阅读者不可见。本文介绍一种新的画小图标的方法,使用svg结合css3的新属性clip-path。这种方法的优点是具备语义性,无论在性能还是占用的空间都具有优势。clip就是裁剪的意思,clip-path原本的用处是用来裁剪图片,如:
对于无法支持的浏览器,改用其它的办法,得做个区分。可以借鉴modernizr提供的办法,页面加载时,首先创建一个svg和一个div,设置这个div的clip-path CSS属性,然后调用getComputedStyle看是否仍有刚刚设置的属性,如果有说明支持,没有说明不支持。如果支持就给body添加一个has-clip-path的类,不支持就为no-clip-path,然后在需要使用图标的元素的css前面加多一个clip-path的类,有和没有两个。这样就达到了区分的目的,不支持的就使用其它的方式。
上面,指定裁剪的路径为一个椭圆,x轴上的半径为裁剪区域的50%,y轴的半径为裁剪区域的40%,圆心在(50%, 50%)的位置。在这个椭圆形的封闭区域外的所有元素都不会被浏览器渲染出来,使用时要带有-webkit-前缀和标准的两种形式。Clippy这个网站可以在线裁剪,当前最新版本的chrome和safari都支持基本形状的裁剪。除了椭圆外还支持rect(长方形)、cirle(圆形)、inset(带圆角的长方形)、polygon(多边形),具体使用可结合上面的博客和网站进行探索。最后一种形式,是使用html里定义的svg元素作为裁剪的目标,这也正是clip-path的生命力所在。因为svg本身提供了丰富的语义定义,可以制作丰富多彩的矢量图形,更重要的是svg可进行可视化编辑,如AI,inkscape,还有一些在线的编辑器,如svg-editor。关于svg的基本介绍,可参考mdn的教程。
它的原理是将一个div的width和height设置成0,那就剩下四个border,四个角都是三角形,令其它三个角不显示,只留下底部那个角,就是一个向上的三角形。要注意设置左右角的宽度,目的是设置三角形上面两条边的长度,再将它们隐藏。更多CSS图形参考css shape。这种方法看似完美,因为无论是空间占用还是解析速度都比前面两个方法好,但是这种方式是不自然的,你无法轻易地改变图形的大小去适应你的页面,如果你不知道它画的原理是怎么样的。第二是无法容易地画出一些较为复杂的图案,例如为了画三个小黄人,花费了2000多行的CSS代码。另外一个缺点是,它是一个空的span或者div,对于屏幕阅读者来说是不可见的。
注意到,icon-font和clip-path本质都是一样的,都是使用了svg,只是使用的方式不同。因此在提供icon font图标的网站上,如icomoon和fontello上,可将图标的svg制作字体,也可作为clip-path使用。
第三种方法是使用CSS的技巧,这种方法一般只适用于比较简单的图案,例如三角形、五角星、爱心等。例如,如果想要画一个向上的三角形可以使用下面的方法:
关于兼容性,IE和edge所有版本不支持clip-path,android的浏览器支持url参数的clip-path,但是UC和微信的内置浏览器不支持,微博的浏览器是支持的,firefox支持带url参数的。chrome支持-webkit-前缀的,包括基本的形状和url,safari/ios支持标准形式的,但是safari/ios在渲染上有bug,只要css文件里出现了clip-path,任何元素只要带position为relative/absolute的都会隐藏掉了,解决办法是,在这些元素里加多一个css属性:-webkit-transform: translateZ(0)加大渲染权重,这样就能显示出来了。还有可能会出现其它无法渲染的情况,例如,同一个id的clip-path只能渲染出第一个,接下来的都消失了,也可以用这种办法解决,但是如果渲染过重,在chrome等其它浏览器会出现显示的问题,会显示错乱。因此这个问题比较麻烦,h5开发的时候需要注意。
icon-font的制作方法可参见博主的另外一篇文章:把UI图里小图标制成icon font
<svg width="0" height="0">
<defs>
<clipPath id="tick-mask" clipPathUnits="objectBoundingBox">
<path fill="red" stroke="red" stroke-width="1" stroke-miterlimit="10" d="m0.1165671,0.4703638l0.0852069,-0.0852042l0.2337128,0.2335306l0.389592,-0.3894064l0.0852045,0.0852087l-0.4747964,0.4747913z" id="svg_8" clip-rule='evenodd'/>
</clipPath>
</defs>
</svg>
除了裁图片,利用clip-path的裁剪功能,可以用来制作图标。原理就是用一个div,设置background颜色和width/height值,然后制作一个图标的svg路径,用来裁剪div,就会显示出相应的小图标了。以打勾的图标为例:
1. CSS vs. SVG: Shapes and Arbitrarily-Shaped UI Components 这篇文章比较了使用CSS和svg画图标的两种方法,强调了使用svg画图的优点。
形状画好了之后,由于要求背景是红色的,勾是白色的,因此先用一个div,设置红色背景和圆角,再用一个白底的span裁出一个勾的形状。如下:
4. Clippy在线操作clip-path
第四种方法是使用icon font,将ui图里的icon导出制作成一个字体库,然后跟正常的字体一样使用,具体制作的方法可参考这篇文章。一般来说,icon font是从svg等矢量格式来的,通过PS导出png的方法可能会存在一些问题。boostrap的glyphicon就是使用icon font。使用时,先用@font-face导入字体(font-face的使用见这篇文章),然后利用一个span,设置font-family为刚刚导入的字体,再通过伪类before或after,属性content的值为对应图标的编码。或者是,直接在html文件里直接插入该图标的编码。如下所示:
<body>
<svg style="display:none" width="0" height="0"><defs><clipPath id="_svg"><path d="M 0 0 L 0 0"></path></clipPath></defs></svg>
<div style="-webkit-clip-path:url(#_svg);clip-path:(#_svg);display:none" id="_test"></div>
<script>
var style = document.defaultView.getComputedStyle(document.getElementById("_test"), null);
var body = document.getElementsByTagName("body")[0];
if(style.WebkitClipPath !== "url(#_svg)" && style.clipPath !== "url(#_svg")
body.className = "no-clip-path";
else
body.className = "has-clip-path";
</script>
<!--body的其它元素-->
</body>
本文由澳门金莎娱乐网站发布于澳门金莎娱乐网站,转载请注明出处:path制作小图标,iconfont实践小结澳门金莎娱乐网
关键词: