在實現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