Web 设计新趋势: 使用 SVG 代替 Web Icon Font

如果你还在使用 Icon Font 作为网页中显示图标的实现方案,那么你可能有点 Out 了。 由于使用 Icon Font 显示图标存在一些缺陷,开发者们一直在致力于探索使用 SVG 作为替代的方法。 这篇文章列举了目前 SVG 比较常见的使用方法。

关于使用 Icon Font 的缺陷,这篇来自 CSS Trick 的 《Inline SVG vs Icon Font》 可谓是总结的相当全面了。在我看来,Icon Font 的主要缺陷有以下几条:

  1. 浏览器将其视为文字进行抗锯齿优化,有时得到的效果并没有想象中那么锐利。 尤其是在不同系统下对文字进行抗锯齿的算法不同,可能会导致显示效果不同。
  2. Icon Font 作为一种字体,Icon 显示的大小和位置可能要受到font-sizeline-heightword-spacing等等 CSS 属性的影响。 Icon 所在容器的 CSS 样式可能对 Icon 的位置产生影响,调整起来很不方便。
  3. 使用上存在不便。首先,加载一个包含数百图标的 Icon Font,却只使用其中几个图标,非常浪费加载时间。 自己制作 Icon Font 以及把多个 Icon Font 中用到的图标整合成一个 Font 也非常不方便。
  4. 为了实现最大程度的浏览器支持,可能要提供至少四种不同类型的字体文件。包括TTFWOFFEOT 以及一个使用 SVG 格式定义的字体。

开发者们想出了多种使用 SVG 的技巧来解决 / 缓解上述问题,下面我们来逐个盘点目前常见的使用方法。

img/object 标签

使用 img 和 object 标签直接引用 SVG 是早期常见的使用方法。 这种方法的缺点主要在于要求每个图标都单独保存成一个 SVG 文件,使用时也是单独请求的。 如果在页面中使用的多个图标,每个都是单独请求的话会产生很多请求数,增加服务端的负载和拖慢页面加载速度, 因此现在很少使用了。

不过,在 IE 中可以使用 object 标签实现最后讨论的 SVG Defs/Symbols 的效果。

Inline SVG

所谓 Inline SVG,就是直接把 SVG 写入 HTML 中,这种方法简单直接,而且具有最强的可调性。 使用这种方法,你可以使用 CSS 的fill属性和stroke属性来控制填充颜色和边线的颜色, 如果 SVG 图标包含多个部分,你甚至可以设置每个部分的样式。同时,使用 JavaScript 修改 SVG 和生成动画效果都可以实现。

Inline SVG 作为 HTML 文档的一部分,不需要单独请求。临时需要修改某个图标的形状也比较方便。 但是 Inline SVG 使用上比较繁琐,需要在页面中插入一大块 SVG 代码因此不适合手写,图标复用起来也比较麻烦。

好在我们大部分的页面都是由某种模板渲染出来的,无论是使用 PHP、Jinja2 还是 ERuby 模板语言, 都可可以定义一个函数来帮我们 include 这些 SVG。因此在很多情况下是很好的解决方案, 其不适合的主要使用场景就是纯静态页面或者前后端分离客户端页面。

Data URIs

Data URIs 是一种不怎么常见的技巧。之前我们在 CSS 里定义元素的背景图片时,常使用像下面这种方式

1
2
3
4
.icon {
  backgound-image: url(icons/a.png)
  /* ... */
}

而现在,url当中可以放置的可以不仅仅是指向资源的 URL 链接,而可以是数据本身。使用 Data URIs,无论是图片还是 SVG, 你都可以将其编码为 base64 并直接写入 CSS。譬如

1
2
3
.icon{
  background: url(data:text/svg+xml;base64,<base64 encoded data>)
}

关于 base64 编码,请参考wiki,Data URI 的格式定义如下

1
data:[<mime type>][;charset=<charset>][;base64],<encoded data>

使用这种方法,SVG Icon 使用起来和 Icon Font 一样只需要为元素添加 CSS 即可,所有的资源都可以整合在一个 CSS 文件中, 不需要额外引用 SVG 文件。 如果你在使用 Gulp 或者 Grunt 这样的 Build 工具,那么将 SVG 整合到一个 CSS 当中是可以非常方便地自动化完成的。这个任务只有简单的字符串和编码处理,基本不需要依赖非 JavaScript 的库和资源。

使用这种方法的缺点是不能方便地使用 CSS 修改 Icon 的颜色和边线属性。

SVG Sprite

目前,一些提供制作 Icon Font 功能的网站 (如icomoon) 已经提供输出 SVG Sprites 功能了。 SVG Sprites 可以看做上述 Data URIs 方法和之前使用位图的 Sprite 方法的组合。

在 Icon Font 还没普及、图标还主要依靠位图显示的时候,前端工程师都会使用 Sprite 来减少图片请求的次数。 其原理很简单:将所有的图标以一定的间隔排列起来组成一整张大图片,使用时对于某个 Icon,编写如下所示的 CSS。

1
2
3
4
5
6
.icon-a {
  background-image: url(/path/to/pic/contains/all/icons.png);
  background-position: 0 120px !important;
  width: 24px;
  height: 24px;
}

上述 CSS 通过设定background-position调整大图片在背景中的位移,只将某个单个 Icon 暴露出来,其他部分都切掉。 对于所有的 Icon 都写成这样的 CSS 即可使用了。基础的 SVG Sprite 其实只是将原来的位图改成了 SVG。

SVG Sprite 相比于原来的位图 Sprite 的一个优点就是可以通过 CSS 调整 Icon 显示的大小。 使用时还可以 Fallback 到位图的 Sprite,因此有极好的浏览器兼容性。 不过和 Data URIs 方法一样它同样存在不能方便调整颜色样式的问题。

目前辅助生成 SVG Sprites 的工具有 grunt-iconizr、 gulp-svg-sprites 等。 使用这两个工具,只需将用到的 SVG 放到某个文件夹中就可以自动被拼合成 Sprite 并输出对应 CSS。 两个工具都支持生成 PNG 格式的位图作为 Fallback,缺点是生成位图要依赖phantomjs这个重量级 JS 库。

SVG Defs/Symbols

SVG Defs 和 Symbols 的原理类似,这里着重介绍一下 SVG Symbols 的使用, SVG Defs/Symbols 本质上是对 Sprite 的进一步优化。之前,我们需要使用相对位置来控制哪个图标被显示出来, 但是其实 SVG 本身的定义允许你以某一种方式直接引用 SVG 中的某一部分。

将多个图标整合成一个 SVG 中的多个 Symbols 之后是下面这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">

    <symbol id="circle-cross" viewBox="0 0 32 32">
      <title>circle-cross icon</title>
      <path d="M16 1.333q2.99 0 5.703 1.161t4.677 3.125 3.125 4.677 1.161 5.703-1.161 5.703-3.125 4.677-4.677 3.125-5.703 1.161-5.703-1.161-4.677-3.125-3.125-4.677-1.161-5.703 1.161-5.703 3.125-4.677 4.677-3.125 5.703-1.161zm0 2.667q-2.438 0-4.661.953t-3.828 2.557-2.557 3.828-.953 4.661.953 4.661 2.557 3.828 3.828 2.557 4.661.953 4.661-.953 3.828-2.557 2.557-3.828.953-4.661-.953-4.661-2.557-3.828-3.828-2.557-4.661-.953zm3.771 6.885q.552 0 .948.391t.396.943-.396.948l-2.833 2.833 2.833 2.823q.396.396.396.938 0 .552-.396.943t-.948.391-.938-.385l-2.833-2.823-2.823 2.823q-.385.385-.948.385-.552 0-.943-.385t-.391-.938q0-.563.385-.948l2.833-2.823-2.833-2.833q-.385-.385-.385-.938t.391-.948.943-.396.948.396l2.823 2.833 2.833-2.833q.396-.396.938-.396z"/>
    </symbol>

    <symbol id="circle-check" viewBox="0 0 32 32">
      <title>circle-check icon</title>
      <path d="M16 1.333q2.99 0 5.703 1.161t4.677 3.125 3.125 4.677 1.161 5.703-1.161 5.703-3.125 4.677-4.677 3.125-5.703 1.161-5.703-1.161-4.677-3.125-3.125-4.677-1.161-5.703 1.161-5.703 3.125-4.677 4.677-3.125 5.703-1.161zm0 2.667q-2.438 0-4.661.953t-3.828 2.557-2.557 3.828-.953 4.661.953 4.661 2.557 3.828 3.828 2.557 4.661.953 4.661-.953 3.828-2.557 2.557-3.828.953-4.661-.953-4.661-2.557-3.828-3.828-2.557-4.661-.953zm4.49 7.99q.552 0 .943.391t.391.943-.396.948l-5.656 5.656q-.385.385-.938.385-.563 0-.948-.385l-2.833-2.823q-.385-.385-.385-.948 0-.552.391-.943t.943-.391.948.396l1.885 1.885 4.708-4.719q.396-.396.948-.396z"/>
    </symbol>

    <!-- .... -->
</svg>

每个 Symbol 设置一个 id 作为引用时的名字。使用 id 引用这个 SVG 中的 Icon 有两种方式。

第一种,将上述 SVG 作为 body 的第一个元素插入在 HTML 中 (Chrome 存在一个 bug 导致不在这里显示不出图像), 此后,在需要显示某个 Icon 的地方插入下面的代码即可:

1
2
3
<svg class="icon">
  <use xlink:href="#circle-cross"></use>
</svg>

这里的use标签直接使用#circle-cross这个 id 引用了 SVG 中的图标。这种方式的浏览器兼容性较好。

我更喜欢的是第二种方式,这种方式不需要在 body 开始的地方插入 SVG,而是使用完整路径引用 Icon。 也就是:

1
2
3
4
5
6
<svg class="icon">
  <use xlink:href="/img/posts/svg-icons.svg#circle-check"></use>
</svg>
<svg class="icon">
  <use xlink:href="/img/posts/svg-icons.svg#circle-cross"></use>
</svg>

显示出来的效果就是下面这个样子 (可以使用浏览器的 Debug 工具来检视下面的代码)。

这种方式使用上跟img标签没有什么太大的差别了。好处在于所有的图标都在一个文件中,因此只会请求一次。 这种不需要像 Sprite 那样繁琐的设置图片的位移。使用 id 命名图标并使用时直接使用 id 引用既直观又简单。 其灵活性和 Inline SVG 几乎一样——你可以设置颜色、边线样式、大小等等。 视浏览器的不同,有时你需要使用作为 SVG 标签的开始。

1
<svg xmlns="http://www.w3.org/2000/svg">

对于 IE 则需要使用object标签代替<svg><use>。关于兼容性讨论详见 这篇文章

除了前面提到过的几个 Gulp 和 Grunt 的插件都已经支持 SVG Defs/Symbols 了之外,这里再推荐一个更轻量的 Gulp 插件 gulp-svg-symbols。如果只使用 SVG Symbols 而无需 Sprite 支持, 那么使用 gulp-svg-symbols 可以免去对 phantomjs 的依赖。

结语

SVG Icons 作为一种 Icon Font 的替代,使用上具有灵活性好、显示效果好、可控性强等诸多优点。 尤其是最后介绍的 SVG Defs/Symbols 这种方式,已经让 SVG Icon 变成了一种实用的解决方案。

浏览器兼容性是前端领域永恒的话题,目前来看对 SVG 的支持情况确实没有 Web Font 那么好, 其中,主流移动浏览器 (Safari, Chrome, IE for Windows Phone) 都已经基本兼容 SVG, 但是桌面领域中仍然要面对 IE8 以下的浏览器,此外对 SVG Defs/Symbols 的支持也还存在差异。

现阶段,如果对浏览器兼容性要求比较严苛 (主要是支持 IE6-8),则可以权衡考虑 Icon Font 和带 Fallback 的 SVG Sprite。 否则的话,推荐使用 SVG Defs/Symbols 的方式代替 Icon Font。

个人认为 SVG Icons 已经具备普及的条件了。

时间: 2024-10-06 01:30:30

Web 设计新趋势: 使用 SVG 代替 Web Icon Font的相关文章

web设计新趋势

2015 年 7 个重要的 Web 设计趋势:Web 设计趋势每一年都会有所变化.但设计师的创意天赋是推动改变网页设计标准的法则.设计师负责将创意转化为趋势.趋势转变为标准.如果在 2015 年,网页缺少以下 7 个设计元素,必定被淘汰. 1.排版更灵活 这部分的主要焦点在于,字体展现会受到新兴排版原则影响. 事实上,网页字体和打印字体还是有很大不同的,在 2015,我们会摆脱过去将文本挤在一起的老式思维. 其实,这并不是什么新鲜事,因为自 2006 年以来一直讨论这个概念,但设计适应缓慢,毕竟

网页设计新趋势响应式导航设计

响应式设计是当前网站设计的趋势,针对不同的设备,提供布局解决方案. 而且很多UI设计技术狂人正在不断的进行各种实验,争取让响应式设计越来越好. 响应式设计的难点是导航菜单界面设计.可不能像缩放页面那样缩放导航菜单.在界面设计之前,要谋划好导航菜单在手机.平板.桌面上的布局.今天蓝蓝设计收集了25例出众的响应式设计,大家可以使用响应式在线测试工具Responsinator来看看,他们的网站设计的导航菜单,是怎样UI设计的. Harvard University Boston Globe Disne

网站设计新趋势:沉浸式交互设计

时间的车轮滚滚向前,不断的改变我们对世界的认知,一些网站和App从大红大紫到门可罗雀也许只需要几个月的时间,但是每一次一种旧技术的终结,也就意味着一种新技术的兴起. 以下是我搜集的曾经受到用户热捧的现代交互设计技术,这些技术有些确实非常新奇,有些只是对旧思想的一些改进,但是不管怎样,这些技术会帮助你走在时代的前列,赶上世界前进的步伐. 一. 动画和过渡 一提及交互设计,我们就会想到一个时下最流行的概念,那就是动画效果,从一个炫酷的悬停到一个全屏化的卡通动漫背景,都属于动效的范畴. 对于交互设计来

移动端设计新趋势:化繁为简

我们在这个"极简主义"的世界生活已经有些时日了,之后又将去向何方? 过去几个月来,设计创新领域的先行者们,将"极简设计"推向了一个新的高度.Facebook.Airbnb和Apple都遵循着近似的原则,简化它们的核心产品,这种"化繁为简"(Complexion Reduction)的新趋势就在它们的移动端设计中得到体现. "化繁为简"究竟是什么? 你是不是从没听说过"化繁为简"的趋势?那是肯定的,因为这只是

软件设计新趋势,云基类该如何实现?

基于云基类的框架设计-2015年末随想2015年马上要结束了,展望2016,对软件开发和设计有些感谢,想和园子里的朋友交流交流. 想想中的开发场景: 一个好的软件架构设计师设计一套好的架构,这套架构运行与云中的服务器,基于架构开发的人员通过“web service” ,“wcf”或其他还没创造出来的技术引用到本地,开发人员在此架构上完善自己的具体业务需求.(“web service” ,“wcf”,之所以加引号,是无法实现目前的想法) 特点:(1)所有的基类实现代码都在云服务器上,开发人员无法接

8大网页设计新趋势(转载)

网页设计属于设计的一种,而设计中最重要的就是要符合潮流,所以网页设计紧跟潮流是必须的,这样才能使你的网页设计有足够的新鲜度以及吸引眼球的能力.下面笔者总结了8点网页设计技巧的新潮流趋势. 一.使用平面设计 以前我们可能会觉得平面设计和网页设计以及UI设计有很大的区别,会平面设计的人可能未必能做好网页设计,但这样的观念是时候革新了.实际上好的平面设计师会将自己的平面设计功底融合到网页设计当中,如果我们在学网页设计的时候只是参照网站设计,那我们永远无法突破. 不论是用平面设计作为背景也好,或者是用平

移动web设计稿尺寸,关于移动web尺寸的那点事

我自己的做稿子的时候,一开始就有一个习惯,先放上这段代码<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />    未隐藏URL栏<meta name="viewport" content="width=device-width, initial-scal

Web 设计与开发者必须知道的 15 个站点

新闻来源:catswhocode.com公司博客整整一个月没有更新了,最近一段时间,全公司都忙于两件事,为海尔集团做定制,为一个合作伙伴做 OEM,终于有了眉目.工作期间,常用到一些工具与帮助站点,今天读到一篇文章,介绍了15个对 Web 设计与开发师极端有用的站点,里面有不少也是我们一直在使用的,也许对很多人都有用,翻译出来以饷同仁. ColorCombos 配色是 Web 设计的首要大事,Color Combos 帮你预备了数千种配色方案,可以根据色调浏览选取.LIpsum Lorem Ip

[转]响应式WEB设计学习(1)—判断屏幕尺寸及百分比的使用

原文地址:http://www.jb51.net/web/70360.html 现在移动设备越来越普及,用户使用智能手机.pad上网页越来越普遍.但是传统的fix型的页面在移动终端上无法很好的显示.因此,Ethan Marcotte提出一种响应式web设计的概念. 响应式web设计的英文为Responsive Web Design,简写为RWD. 在图书馆借到一本O'REILLY的<Head First Moblie Web>,里面讲到了一些做RWD的技巧. 今天学到的两招是: 1.使用med