在实现Web项目的图标系统时,SVG是一个不错的选择。虽然使用SVG建立图标系统有多种方式。在这篇文章中,咱们只看其中一种:SVG symbols。这项技术基于两个元素的使用:<symbol>
和<use>
。css
<symbol>
元素用来对元素进行分组;它不会被直接显示,大概至关于定义一个模板,而后使用<use>
元素引用并进行渲染。html
咱们使用Illustrator建立并导出SVG图标:git
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24"> <path fill="#E86C60" 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> </svg>
而后将内容包裹在<symbol>
元素中:github
<svg> <symbol viewBox="0 0 24 24" id="heart"> <path fill="#E86C60" 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>
如今若是咱们把这段代码插入到咱们的页面中,咱们会看到图标并不显示,由于要显示图标,咱们还须要使用<use>
元素:浏览器
<body> <svg style="display: none;"> <symbol viewBox="0 0 24 24" id="heart"> <path fill="#E86C60" 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> <use xlink:href="#heart"/> <!-- this is our visible icon --> </svg> </body>
结果以下:缓存
换句话说,就是你定义了一组图形对象(使用<symbol>
元素)以后,可使用<use>
元素来对它进行无限次实例化展现。你使用xlink:href
属性来指定你想要展现哪一组图标,这里,咱们要展现的是id
为#heart
的<symbol>
元素。app
你可能注意到了咱们给包裹<symbol>
元素的SVG标签加了一个style="display: none;"
的样式:这是由于即便<symbol>
自己没有显示,可是包裹它的<svg>
元素依旧会渲染并占用一些页面空间,这就是为何咱们须要隐藏svg元素。svg
如今咱们知道了<symbol>
和<use>
元素分别是什么,以及它们是如何工做的,咱们能够来创建咱们的SVG sprite了。工具
首先,你须要准备好全部图标,每一个图标放一个单独的.svg
文件。而后再建立一个新的(空白的).svg
文件(我把它命名为myicons.svg
)。网站
在这个新的svg文件中,插入一个<svg>
标签,而后,对于每个你要放进去的图标,分别用一个<symbol>
元素来包裹。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <symbol viewBox="0 0 24 24" id="heart"> <path fill="#E86C60" 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> <symbol viewBox="0 0 32 32" id="arrow"> <path fill="#0f0f0f" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22.8,13.6l-6,8C16.6,21.9,16.3,22,16,22 s-0.6-0.1-0.8-0.4l-6-8c-0.2-0.3-0.3-0.7-0.1-1S9.6,12,10,12h12c0.4,0,0.7,0.2,0.9,0.6S23,13.3,22.8,13.6z"></path> </symbol> </svg>
每一个<symbol>
元素都设置一个id
,这个id
用来在后面使用<use>
的时候引用。
咱们还给每一个<symbol>
元素指定了一个viewBox
属性。这个viewBox
属性定义了图标的宽高比;它包含4个值,前面2个值一般为0
(但它实际上是依赖于图标是如何绘制的),另外两个值分别是SVG的宽和高(若是你对于viewBox
属性不熟悉,能够看看这篇关于SVG缩放的文章)。
这样你的图标不须要保持相同的宽高比,由于你能够给每一个图标分别定义不一样的viewBox
属性。
最后一步,咱们能够给每一个图标添加一个<title>
标签,提高它的可访问性。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <symbol viewBox="0 0 24 24" id="heart"> <title>Heart</title> <path fill="#E86C60" 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> <symbol viewBox="0 0 32 32" id="arrow"> <title>Arrow</title> <path fill="#0f0f0f" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22.8,13.6l-6,8C16.6,21.9,16.3,22,16,22 s-0.6-0.1-0.8-0.4l-6-8c-0.2-0.3-0.3-0.7-0.1-1S9.6,12,10,12h12c0.4,0,0.7,0.2,0.9,0.6S23,13.3,22.8,13.6z"></path> </symbol> </svg>
咱们的SVG sprite如今能够投入使用了。你能够保存文件为myicons.svg
,放在资源文件夹中(我一般把这个文件夹明明为img
)。
接下来展现咱们的图标,你须要作的就是在文档中你想要放置图标的位置插入下面这一小段:
<svg> <use xlink:href="img/myicons.svg#heart"/> </svg>
就这样,so easy!
浏览器兼容性如何呢?在IE中经过<use>
引用外部SVG文件的方法是不可行的,IE9以上也不行(不过,这个问题在Edge中已经解决了)。
那要如何解决呢?咱们来看看两种可能的解决方案。
咱们能够在文档的顶部引入SVG sprite,而后使用<use>
标签引用图标:
<svg style="display: none;"> <!-- this is our svg sprite --> <symbol viewBox="0 0 24 24" id="heart"> <path fill="#E86C60" 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> <symbol viewBox="0 0 32 32" id="arrow"> <!-- ... --> </symbol> </svg> <svg> <use xlink:href="#heart"/> <!-- this is our visible icon --> </svg>
注意xlink:href
属性和id标识符是惟一对应的(它不能引用外部资源中的id)。
这种方法很是好用,但缺点是SVG sprite不能缓存。
咱们可使用一个polyfill;举个例子,svgxuse。这个polyfill能够根据<use>
元素的引用,获取外部SVG资源中的id
,而浏览器自己并不能这样作。基本远离就是,这个polyfill遍历文档中的<use>
元素,而后若是它引用的是浏览器没法加载的外部SVG文件,它就在外部SVG中抓取并预置到文档中的<body>
中。good!
你能够在Github repo中下载这个polyfill,在文档中引入,就ok了。
注意:SVG只在IE9以上支持;因此若是你须要支持IE8及如下的浏览器,你须要另外再写一套降级(例如,使用png图片方案)。
接下来,怎么给SVG添加样式呢?给SVG <use>
元素添加样式须要一点技巧。这是由于SVG 图标引用这种方式有本身单独的DOM结构(也就是shadow DOM),CSS选择器并不能获取到,因此假设咱们有以下的图标:
<svg class="icon"> <use xlink:href="img/myicons.svg#heart"/> </svg>
而后这样添加样式:
.icon path { fill: #000000; }
是没有办法工做的。
如何解决这个问题呢?好比说你想要改变图标的填充颜色。首先,确保fill
属性不是svg文件中内联定义的。因此,若是图标 sprite以下:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <symbol viewBox="0 0 24 24" id="heart"> <title>Heart</title> <path fill="#E86C60" 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> <symbol viewBox="0 0 32 32" id="arrow"> <title>Arrow</title> <path fill="#0f0f0f" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22.8,13.6l-6,8C16.6,21.9,16.3,22,16,22 s-0.6-0.1-0.8-0.4l-6-8c-0.2-0.3-0.3-0.7-0.1-1S9.6,12,10,12h12c0.4,0,0.7,0.2,0.9,0.6S23,13.3,22.8,13.6z"></path> </symbol> </svg>
把内联fill
属性删除,以下:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <symbol viewBox="0 0 24 24" id="heart"> <title>Heart</title> <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> <symbol viewBox="0 0 32 32" id="arrow"> <title>Arrow</title> <path d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z M22.8,13.6l-6,8C16.6,21.9,16.3,22,16,22 s-0.6-0.1-0.8-0.4l-6-8c-0.2-0.3-0.3-0.7-0.1-1S9.6,12,10,12h12c0.4,0,0.7,0.2,0.9,0.6S23,13.3,22.8,13.6z"></path> </symbol> </svg>
而后在你的css代码中,加入:
.icon { fill: #00000; /* this will be your icons default color */ }
由于你没有在SVG中给path
元素指定fill
,因此它们会继承父级元素,即SVG的fill
属性,这样你能够直接使用CSS选择器修改这个属性。
如今,若是咱们只想改变一个图标的fill
,怎么办呢?咱们给这个图标再单独指定一个class
便可:
<svg class="icon my-class-name"> <use xlink:href="img/myicons.svg#heart"></use> <svg>
而后使用CSS改变它的fill
值:
.my-class-name { fill: red; }
手动建立一个SVG symbol sprite是很是麻烦的,特别是若是你有相对多的图标。Nucleo自动化SVG symbol sprites构建工具能够帮助你省下不少琐碎活。
从Nucleo的网站上,选择你想要下载图标,而后点击下载按钮。在弹出的设置窗口中,勾上‘Export as <symbol>
选项,而后填写你的资源文件夹的路径(这里会为<use>
元素设置一个xlink:href
值);填写一个文件名(这是你的SVG sprite文件的名字)。而后点击保存。完成啦!你的sprite就能够用了。
你下载的文件夹中会包含几样东西:
style.css
文件(在css文件夹中):它包含基本的SVG样式(例如,你在app中设置的fill
/stroke
属性);你须要复制这块内容到你的样式文件中(或者做为一个额外的css文件引入);svgxuse.min.js
文件(在js文件夹中),这是针对IE9+的polyfill;你须要在你的文档中引入这个文件,若是你但愿图标在IE9+的浏览器中能够正确显示的话;demo.html
文件。基本上,这个demo文件列出了全部你下载的图标,你能够直接在你的文档中引入它们:点击你想要引入的图标,它就会选中你须要复制的代码片断,而后在你的文档中粘贴便可。
图标也会按照你在Nucleo app中设置的样式显示。
怎么给单个图标添加样式呢?你能够给图标指定一个class
:
<svg class="nc-icon grid-32 glyph my-class-name"> <use xlink:href="img/myicons.svg#double-left"/> </svg>
而后在CSS中修改:
.my-class-name { color: purple; }
OK。可是,Nucleo图标是双色的....若是我想改变的是其中的第二种颜色的?这也好办,加上:
.my-class-name use { color: orange; }
OK啦。
咱们的symbols有一些额外的技巧。
stroke
。若是你想要改变某个图标的stroke-width
属性呢?假设你下载的图标stroke-width
为2px
,那么stroke-2
类会自动添加到SVG元素上。若是你想要把stroke
切换为3px
,只须要把stroke-2
类改成stroke-3
类就能够啦。xlink;href
属性设置为和<symbol>
的惟一标识符id相等的名字。使用SVG symbols真的是管理图标的很是智能的方法;这是为何咱们在Nucleo中加入了'symbol export'功能。
使用Nucleo管理图标也是很是方便的,即便你手头有多个项目:你须要作的只是建立一个项目,添加你须要的图标,而后点击几下,下载便可。
本文根据@Claudia Romano的《How to create an icon system using SVG symbols》所译,整个译文带有咱们本身的理解与思想,若是译得很差或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:https://nucleoapp.com/how-to-create-an-icon-system-using-svg-symbols/。
著做权归做者全部。
商业转载请联系做者得到受权,非商业转载请注明出处。
原文: http://www.w3cplus.com/svg/how-to-create-an-icon-system-using-svg-symbols.html © w3cplus.com