使用SVG symbols建立圖標系統
在實現Web項目的圖標系統時,SVG是一個不錯的選擇。雖然使用SVG創建圖標系統有多種方式。在這篇文章中,我們只看其中一種:SVG symbols。這項技術基於兩個元素的使用:<symbol>
和<use>
。
<symbol>
元素用來對元素進行分組;它不會被直接顯示,大概相當於定義一個模板,然後使用<use>
元素引用並進行渲染。
我們使用Illustrator創建並導出SVG圖標:
<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>
元素中:
<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>
元素。
你可能註意到了我們給包裹<symbol>
元素的SVG標簽加了一個style="display: none;"
的樣式:這是因為即使<symbol>
本身沒有顯示,但是包裹它的<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;
}
使用Nucleo創建SVG symbol sprite
手動創建一個SVG symbol sprite是非常麻煩的,特別是如果你有相對多的圖標。Nucleo自動化SVG symbol sprites構建工具可以幫助你省下很多瑣碎活。
從Nucleo的網站上,選擇你想要下載圖標,然後點擊下載按鈕。在彈出的設置窗口中,勾上‘Export as <symbol>
選項,然後填寫你的資源文件夾的路徑(這裏會為<use>
元素設置一個xlink:href
值);填寫一個文件名(這是你的SVG sprite文件的名字)。然後點擊保存。完成啦!你的sprite就可以用了。
你下載的文件夾中會包含幾樣東西:
- 你的SVG 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
類就可以啦。 - 那如何讓圖標和文本對齊呢?在demo文件中,在頂部,可以選擇‘align to text’;然後復制SVG片段並粘貼到你的文檔中(感謝Cloud Four提供的‘align to text‘樣式)。 註意,在這裏,SVG會繼承文本的顏色;但是,你同樣可以使用一個自定義類,給它添加自定義樣式,和前面一樣。
- 如果你更傾向於在文檔中引入SVG sprite(而不是作為一個外部的SVG文件引用),不要勾選‘Reference external SVG‘選項(在demo文件的頂部);這會自動將
xlink;href
屬性設置為和<symbol>
的唯一標識符id相等的名字。
使用SVG symbols真的是管理圖標的非常智能的方法;這是為什麽我們在Nucleo中加入了‘symbol export‘功能。
使用Nucleo管理圖標也是非常方便的,即使你手頭有多個項目:你需要做的只是創建一個項目,添加你需要的圖標,然後點擊幾下,下載即可。
[email protected] 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
使用SVG symbols建立圖標系統