A picture is worth a thousand words, 一图胜千言。 没错,从 Web 诞生的那天开始,图标就成为视觉层面不可或缺的一个元素,在一个 Web 页面中,一个图标不仅仅能从视觉上带来优雅感,更重要的是,它对此处的功能起到了点睛之笔的作用,它会使得用户更容易理解你的产品。那么,在我们当下的 Web 前端开发中,最常见的图标解决方案有哪些呢?大概是三种,图片、IconFont 和 Svg。图片就不说了,就是整一坨小的 png 图片作为图标,最终把他们合在一个图片里,此种技术还有一个好听的名字 CSS Sprites
,国人称为 雪碧图
,此种方案还是 Web 前端性能优化军规之一,降低 http 请求数来达到提速的目的。
图片咱们今天不说了,没啥意思。咱们今天聊聊 IconFont 和 inline SVG,然后把这两个方案的优劣进行一个对比,然后再介绍介绍常见的 IconFont 库及 inline SVG 的库,最后再展示一个小 Demo 给大家看一看具体在页面上 IconFont 和 Svg 有什么不同。
IconFont 使用的技术是 CSS 自定义字体,用户可以把图标集合打包成字体文件 ( 如何打包,可使用 iconfont.cn ),然后通过 @font-face 来自定义一个字体,最后通过设置 font-family
以及通过使用图标字体的 unicode编码
来使用图标。
在 CSS 里声明字体,编写 unicode 编码对应的图标:
@font-face { font-family: 'FontAwesome'; src: url('../fonts/fontawesome-webfont.eot?v=4.6.3'); src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.6.3') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.6.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.6.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } .fa { font-family: 'FontAwesome'; display: inline-block; } .fa-icon:after { content: '/f00c' }
在 HTML 里这么写就可以了:
<i class="fa-icon"></i>
IconFont 有大量的开源解决方案,而且有很多现成的图标,比较具有代表性的如下:
FontAwesome ,具备完善大量的图标库,对于定制化程度不高的项目,可以直接拿过来用
Iconfont.cn ,阿里的解决方案,不但有现成的图标供你选择,还可以上传自己的图标来制作 IconFont
IconFont 的最大的好处就是浏览器兼容性好(IE6+),可以通过 CSS 来控制图标大小、颜色。
使用 IconFont 是把已有的矢量文件(通常是很多 .svg 文件)打包成字体文件,而 inline SVG 则是把 .svg 文件合并成一个大的 .svg 文件,然后在 HTML 中引用这个文件即可,具体步骤参考下面。
在这里搞了三个 svg 文件,准备把他们合并在一起:
<img style="display:block;width:100%;float:none;" src=" http://ww4.sinaimg.cn/large/8df27f17gw1f4b11i2l79j20xe0i0acj.jpg"/>
我这里使用的是 svg-symbol 方案来合并 svg。
还有一个合并方法是 SVG defs ,这个比 SVG Symbol
要鸡肋很多,在此就不介绍了。
通过使用 gulp-svg-symbols 来把 svg 文件合并:
var gulp = require('gulp'); var svgSymbols = require('gulp-svg-symbols'); gulp.task('sprites', function () { return gulp.src('assets/svg/*.svg') .pipe(svgSymbols()) .pipe(gulp.dest('assets')); });
最终得到的 svg 文件:
<svg xmlns="http://www.w3.org/2000/svg" style="width:0; height:0; visibility:hidden;"> <symbol id="circle" viewBox="0 0 200 200"> <g class="transform-group"> <g transform="scale(0.1953125, 0.1953125)"> <path d="..." fill="#272636"/> </g> </g> </symbol> <symbol id="password" viewBox="0 0 200 200"> <g class="transform-group"> <g transform="scale(0.1953125, 0.1953125)"> <path d="..." fill="#272636"/> </g> </g> </symbol> <symbol id="profile" viewBox="0 0 200 200"> <g class="transform-group"> <g transform="scale(0.1953125, 0.1953125)"> <path d="..." fill="#272636"/> </g> </g> </symbol> </svg>
在 HTML 文件中声明 svg,然后通过 <svg><use xlink:href="#id" /></svg>
来使用:
<svg xmlns="http://www.w3.org/2000/svg" style="width:0; height:0; visibility:hidden;"> <symbol id="circle" viewBox="0 0 200 200"> <g class="transform-group"> <g transform="scale(0.1953125, 0.1953125)"> <path d="..." fill="#272636"/> </g> </g> </symbol> <symbol id="password" viewBox="0 0 200 200"> <g class="transform-group"> <g transform="scale(0.1953125, 0.1953125)"> <path d="..." fill="#272636"/> </g> </g> </symbol> <symbol id="profile" viewBox="0 0 200 200"> <g class="transform-group"> <g transform="scale(0.1953125, 0.1953125)"> <path d="..." fill="#272636"/> </g> </g> </symbol> </svg> <svg class="icon"><use xlink:href="#profile" /></svg> <svg class="icon"><use xlink:href="#password" /></svg> <svg class="icon"><use xlink:href="#circle" /></svg>
你也可以通过 <svg><use xlink:href="http://cdn.com/assets/symbols.svg#id" /></svg>
来直接使用存储在 CDN 上的 svg 文件,如果感觉每个都要写 CDN 的地址太麻烦,则可以封装 JS 工具,统一维护,统一管理。
inline SVG 目前没有什么特别推荐的开源解决方案,一般情况下,图标都是自己的,自己通过工具打包就已经很方便了,而且很难通过纯 CSS 或 JS 来解决,因为它跟 HTML 的关联性太大了,即使是这样,还是推荐一个库给大家了解了解:
SVGInjector
IconFont | inline SVG |
---|---|
IE6+ | IE9+ , Android 3.0+ 移动端支持很好,现在可以使用 |
IconFont | inline SVG |
---|---|
浏览器会认为它是一个字体,因此只能使用 color 和 font-size 控制,而且尺寸特别不精细 | 支持多色、局部颜色控制、控制尺寸使用 width 和 height |
IconFont | inline SVG |
---|---|
Font 在 CDN 上会有跨域问题;而且字体下载不下来是很常见的事;还有一些 已知的Chrome的Bug ;貌似代理性质的浏览器,像 UC ,就不支持自定义 Font;一些浏览器拦截插件会拦截自定义字体...... | Svg很正常 |
IconFont | inline SVG |
---|---|
根本不语义化,你要写多余没有意义的标签,对 SEO 很不利 | Svg 是图形,人家就是图形,而且 SVG Symbol 支持 title 和 description 属性,非常友好 |
IconFont | inline SVG |
---|---|
自己生成 svg 然后使用工具打包成多个字体文件,然后用 unicode 对应使用 | SVG Symbol 使用打包工具生成 SVG 集合,直接通过 ID 使用 |
请去我的CodePen
如果,你的产品需要支持 IE8 及以下,还是推荐使用 IconFont ,因为使用 SVG Symbol 的话,你需要考虑在低端浏览器下的兼容性,常见的做法是,生成一些 png 的图片做 fallback,然后在低端浏览器下显示,把 svg 隐藏.....
如果,你只需要考虑 IE9+ 和 Android 3.0 + ,毫无疑问,inline SVG 是唯一选择!