iconfont解決了咱們之前大量使用小圖標帶來的種種問題,可是也有自身的各類缺陷。好比不支持多色,不一樣瀏覽器下的表現不一樣,須要作各類兼容等。javascript
不久的未來iconfont應該會被svg symbol技術替換。本文就是介紹如何在網頁中使用SVG圖標。順帶一提螞蟻金服的Ant.Design已經把方案從原來的字體圖標轉到SVG圖標。css
當你從設計師那裏或者繪圖工具(如 Illustrator、 Adobe Assets、 Sketch、 Inkscape等)中拿到 SVG 圖標時,你可能會直接放到網頁中,可是,若是能把圖標(用你經常使用的處理工具)稍微處理下,能夠避免很多頭疼的問題。html
圖標在 Illustrator (左) 和 Sketch (右)的畫板上顯示效果前端
在經常使用的繪圖工具中新建一個文件或者畫板,將圖標複製粘貼到中間,最好確保圖標是純淨的,沒有隱藏圖層。java
圖標不須要非得是正方形的,除非圖標太寬或者過高,不然仍是建議作成正方形的圖標,更好處理。當你有像素級的需求時,好比想要在低分辨率屏幕上得到更好的顯示效果,就須要肯定圖標尺寸。好比圖標須要適應 15x15 px 的網格,並且用的時候也可能是這個尺寸時,就應該去建立 15x15 px 的畫板。不肯定的時候,通常建議選擇 20x20 的尺寸。react
在邊緣區域留一點點空白,特別是對圓形圖標。瀏覽器渲染 SVG 時會作抗鋸齒處理,可是,有時抗鋸齒產生的額外像素點會跑到 viewBox 的外面,從而致使圖標的邊緣看上去被切掉了一部分,看起來有點方。webpack
圖標邊緣未作留白處理,因此可能邊緣渲染出方形的邊,當瀏覽器對 SVG 的渲染不給力時,效果更糟糕。git
所以,每次處理 16px 或 20px 的圖標時,要記得在每一個邊緣留 0.5px 或 1px 的空白,還要記得導出整個畫板,而不是選中位於中間的路徑,不然邊緣的留白是不會導出。github
在 Illustrator 中,選擇 「Save As」 並選擇格式爲 「SVG」(也許選擇 「Export as…」 會更好)。
在 Sketch 中,先選中畫板,點擊右下角 「Make Exportable」,並選擇格式爲 「SVG」。
在 Inkscape 中,選擇 「Save As」 並選擇格式爲 「Optimized SVG」。
關於 SVG 的知識點web
你可能學習過關於 SVG 的基礎知識,而且能讀懂 SVG 的結構。至少你知道:
SVG 元素: <svg>,<symbol> ,<g>, <path>
SVG 屬性: d, fill, stroke, stroke-width
注意:從繪圖工具中導出的 SVG 常常帶着一些沒必要要的內容和標籤等(其中 d 下面包含了清晰的路徑數據),可使用工具好比 SVGOMG ,而後比較一下處理先後哪些東西是移除或簡化過的。
對於單色圖標,確保:
在源文件中, path 的顏色都是黑色(#000000)。
在導出的 SVG 文件中,沒有 fill 屬性。
若是咱們在 SVG 文件中設置了 fill 屬性,就不能經過 CSS 來改變顏色了,因此最好把顏色相關數據都刪掉,至少對單色的圖標這樣。
Illustrator 導出的SVG 中 path 都是黑色(#000000)且不帶 fill 屬性,但 Sketch 導出的文件會帶,得本身手動刪掉像 fill="#000000" 這種屬性。
這一部分會包含很多代碼,但內容其實並不複雜。咱們將建立包含多個 <symbol> 元素的 SVG 文件,每一個 <symbol> 都有id 和 viewBox 屬性,且包含圖標的 <path> 元素(或者其餘元素如<circle> 、 <rect> 等)。
我將這個 SVG 文件稱爲 SVG sprite,也能夠被稱爲 sprite sheet 或者 symbol store。
下面的 SVG sprite 中僅包含一個圖標:
<svg xmlns="http://www.w3.org/2000/svg"> <symbol id="cross" viewBox="0 0 20 20"> <path d="M17.1 5.2l-2.6-2.6-4.6 4.7-4.7-4.7-2.5 2.6 4.7 4.7-4.7 4.7 2.5 2.5 4.7-4.7 4.6 4.7 2.6-2.5-4.7-4.7"/> </symbol> </svg>
下面是 Illustrator 導出的 SVG 圖標的代碼:
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 15 15" style="enable-background:new 0 0 15 15;" xml:space="preserve"> <path id="ARROW" d="M7.5,0.5c3.9,0,7,3.1,7,7c0,3.9-3.1,7-7,7c-3.9,0-7-3.1-7-7l0,0C0.5,3.6,3.6,0.5,7.5,0.5 C7.5,0.5,7.5,0.5,7.5,0.5L7.5,0.5L7.5,0.5z M6.1,4.7v5.6l4.2-2.8L6.1,4.7z"/> </svg>
咱們把這個圖標簡化下(手工或者經過 SVGOMG 處理),只保留 viewBox 屬性及必要的部分:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"> <path d="M7.5,0.5c3.9,0,7,3.1,7,7c0,3.9-3.1,7-7,7c-3.9,0-7-3.1-7-7l0,0C0.5,3.6,3.6,0.5,7.5,0.5 C7.5,0.5,7.5,0.5,7.5,0.5L7.5,0.5L7.5,0.5z M6.1,4.7v5.6l4.2-2.8L6.1,4.7z"/> </svg>
將 <svg viewBox="…"> 寫成 <symbol id="…" viewBox="…"> 格式,放到 SVG sprite 文件中去。
<svg xmlns="http://www.w3.org/2000/svg"> <symbol id="cross" viewBox="0 0 20 20"> <path d="M17.1 5.2l-2.6-2.6-4.6 4.7-4.7-4.7-2.5 2.6 4.7 4.7-4.7 4.7 2.5 2.5 4.7-4.7 4.6 4.7 2.6-2.5-4.7-4.7"/> </symbol> <symbol id="play" viewBox="0 0 15 15"> <path d="M7.5,0.5c3.9,0,7,3.1,7,7c0,3.9-3.1,7-7,7c-3.9,0-7-3.1-7-7l0,0C0.5,3.6,3.6,0.5,7.5,0.5 C7.5,0.5,7.5,0.5,7.5,0.5L7.5,0.5L7.5,0.5z M6.1,4.7v5.6l4.2-2.8L6.1,4.7z"/> </symbol> </svg>
你能夠選擇手動處理全部圖標,也能夠選擇使用工具處理,咱們用了 gulp-svg-sprite
插件,還有不少圖形工具和命令行工具能夠導出 SVG sprite 文件,好比Icomoon。
建議:icon文件放到同一文件夾統一管理
若是你手動建立 SVG sprite,我建議爲 SVG 圖標專門開一個文件夾。
assets/ icons/ cross.svg play.svg search.svg ... public/ sprite/ icons.svg
當你須要從新構建 icons.svg 或者修改某個圖標時,你仍然能夠找到圖標的源文件(在icons 文件夾中)。請儘可能保持 SVG sprite 文件與源文件同步。固然若是你有 Grunt/Gulp 作自動構建打包時,你只須要維護一份圖標源文件(即icons 文件夾)。
爲了使用 SVG 圖標,咱們得把它放到 HTML 中去,咱們不能用 CSS 的 background 相關屬性,不能使用 ::before 等僞元素。用法以下:
<svg><use xlink:href="/path/to/icons.svg#play"></use></svg>
目前有幾種方案能夠爲圖標增長替代文本,通過咱們本身的屏幕語音閱讀測試,下面給出咱們用的方案。
首先,當不須要增長替代文本時(網頁上常常已經存在相關文字內容了),能夠設置 aria-hidden="true" 來確保屏幕語音閱讀時會跳過圖標:
<a href="/news/"> <svg aria-hidden="true"> <use xlink:href="/path/to/icons.svg#newspaper"></use> </svg> Latest News </a>
其次,當遇到 a 標籤或者 button 的內容是圖標時,咱們會在上面設置aria-label 。
<a href="/news/" aria-label="Latest News"> <svg aria-hidden="true"> <use xlink:href="/path/to/icons.svg#newspaper"></use> </svg> </a>
還有一種選擇是使用 <title> 標籤,尤爲是標籤相互做用時致使 aria-label 失效。舉個例子,當你在 table 中使用 yes/no 標記,你能夠這樣:
<tr> <svg> <title>Yes</title> <use xlink:href="/path/to/icons.svg#tick"></use> </svg> </tr>
最後,切記:
替代文本因根據內容來定(好比放大鏡圖標的替代文本爲「顯示搜索框「或者」提交搜索「)。
替代文本要作國際化。
替代文本應該根據 HTML 內容的上下文而定,有人推薦在 SVG sprite 裏面增長 <title> 標籤,可是咱們實踐後發現並不老是生效,不少屏幕語音閱讀都會忽略。
目前爲止咱們所提到的都是外部的 sprite,可是老版本的WebKit 內核瀏覽器和全部版本的 IE 瀏覽器(低於Edge 13),只支持 <use xlink:href="#some-id"/> 這種內聯的引用。能夠考慮引入好比svg4everybody
, svgxuse
等來 ployfill,或者將 SVG sprite 元素寫到每一個頁面的 HTML 中去。
<body> <!-- Hidden icon data --> <svg aria-hidden="true" style="display:none"> <symbol id="icon-play">…</symbol> <symbol id="icon-cross">…</symbol> <symbol id="icon-search">…</symbol> </svg> <!-- A visible icon: --> <button aria-label="Start playback"> <svg aria-hidden="true"><use xlink:href="#icon-play"/></svg> </button> </body>
兩種方法各有利弊,比較以下:
我喜歡將兩種方法混起來用,建立兩個 SVG sprite:
一個小一點的 SVG sprite 包含經常使用的圖標,做爲內聯元素放到每一個頁面中,大小 5KB 之內。
一個大一點的 SVG sprite 包含所有的圖標,做爲外部靜態資源,大小 50KB 之內。
在大一點的項目中,咱們能夠將圖標分組打包成多個 SVG sprite ,服務於網站的某一部分或者某一特定功能。
譯者注:本部份內容與原文無關,是譯者爲展現在 Webpack 中使用 SVG icon 的示例。
在平常開發中,我不知道各位前端朋友們有沒有碰到一個問題,就是使用font-awesome
或相似的icon-font 包,沒法知足設計稿中的需求,好比說來了一箇中國地圖形狀的 icon,你會怎麼辦?
若是專門爲項目維護一份 icon-font 的話,可能須要設計師每次幫你作一份字體文件,每次增長圖標就要去找設計師幫忙,而後再打包生成 ttf 、woff 、 woff2 、eot 一堆文件,至少對於我來講是這樣的。
此外,目前而言,Vue.js 和 React.js 的兼容性都是 IE9 +,因此若是不用管IE 9如下的兼容性,果斷用 SVG sprite 來作圖標啊。
示例將分別介紹 Vue.js 和 React.js 中的用法,工具包括:
使用了svg-sprite-loader
製做 SVG sprite。
使用了svgo-loader
來去除沒必要要屬性(如Sketch導出的 SVG 文件),以簡化 SVG 圖標源碼。
圖標統一放在 assets/icons 文件夾目錄下:
assets/ icons/ cross.svg play.svg heart1.svg ... icon-set.js
在 icon-set.js 中 export 全部圖標:
import Check from './icons/check.svg' import Cross from './icons/cross.svg' import Heart1 from './icons/heart1.svg' ... export { Check, Cross, Heart1, ... }
webpack 配置中增長 svgo-loader
和 svg-sprite-loader
:
var svgoConfig = require('./svgo-config.json') module.exports = { preLoaders: [ { test: /\.svg$/, loader: 'svgo?' + JSON.stringify(svgoConfig) } ], loaders: [ ... { test: /\.svg$/, loader: 'svg-sprite', include: /assets\/icons/ }, ... ] }
svgo-config.json
內容以下:
{ "plugins": [ { "cleanupAttrs": true }, { "cleanupEnableBackground": true }, { "cleanupIDs": true }, { "cleanupListOfValues": true }, { "cleanupNumericValues": true }, { "collapseGroups": true }, { "convertColors": true }, { "convertPathData": true }, { "convertShapeToPath": true }, { "convertStyleToAttrs": true }, { "convertTransform": true }, { "mergePaths": true }, { "moveElemsAttrsToGroup": true }, { "moveGroupAttrsToElems": true }, { "removeComments": true }, { "removeDesc": true }, { "removeDimensions": true }, { "removeDoctype": true }, { "removeEditorsNSData": true }, { "removeEmptyAttrs": true }, { "removeEmptyContainers": true }, { "removeEmptyText": true }, { "removeHiddenElems": true }, { "removeMetadata": true }, { "removeNonInheritableGroupAttrs": true }, { "removeRasterImages": true }, { "removeTitle": true }, { "removeUnknownsAndDefaults": true }, { "removeUselessDefs": true }, { "removeUnusedNS": true }, { "removeUselessStrokeAndFill": true }, { "removeXMLProcInst": true }, { "sortAttrs": true } ] }
這段配置是根據 SVGOMG 裏的配置文件 複製出來的,根據這段配置文件配合 svgo-loader
能夠取代手工去作圖標 SVG 源文件的處理(svgo-loader禁止移除 fill
屬性 ;-D),固然你也能夠本身去定義配置以簡化 SVG 源文件。
備註: 本來 SVGOMG 裏面有一項配置 transformsWithOnePath: true
,因爲這項配置會致使已經處理的 「乾淨」 的 SVG 圖標報錯,因此移除了該選項。此外爲保留 viewBox,還移除了 removeViewBox: true
選項。
此時的SVG文件經過 svg-sprite-loader 處理生成 SVG sprite,並插在 <body> 裏爲首個元素:
<body> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0;visibility:hidden"> <defs> <symbol viewBox="0 0 20 20" id="check"> <path d="M10 1c-4.962 0-9 4.038-9 9 0 4.963 4.038 9 9 9 4.963 0 9-4.037 9-9 0-4.962-4.037-9-9-9zm0 16.615c-4.2 0-7.615-3.416-7.615-7.615C2.385 5.8 5.8 2.385 10 2.385c4.2 0 7.615 3.416 7.615 7.615 0 4.2-3.416 7.615-7.615 7.615z" fill="currentColor"></path> <path d="M13.664 6.74l-5.05 5.05-2.278-2.28c-.27-.27-.71-.27-.98 0s-.27.71 0 .98l2.77 2.77c.135.134.312.202.49.202.177 0 .354-.068.49-.203l5.537-5.54c.27-.27.27-.708 0-.98-.27-.27-.708-.27-.98 0z"></path> </symbol> <symbol viewBox="0 0 20 20" id="cross"> <path d="M19 4.23L15.75 1 10 6.83 4.12 1 1 4.23l5.88 5.83L1 15.9 4.13 19 10 13.17 15.75 19 19 15.9l-5.88-5.84"></path> </symbol> <symbol viewBox="0 0 20 20" id="heart1"> <path d="M18.98 5.7c-.24-2.36-2.24-4.2-4.66-4.2-1.95 0-3.6 1.18-4.32 2.87-.7-1.7-2.37-2.87-4.32-2.87-2.42 0-4.42 1.84-4.66 4.2L1 6.18c0 5.7 6.98 8.38 9 12.17 2.02-3.8 9-6.48 9-12.17 0-.16 0-.32-.02-.48z"></path> </symbol> ... </defs> </svg> ... </body>
而 import Check from './icons/check.svg'
中 Check 就是對應的 <symbol> 的 id。
<template> ... <svg class="Icon" aria-hidden="true"> <use :xlink:href="iconSet.Check"></use> </svg> ... </template> <script> import * as iconSet from '../assets/icon-set' export default { data () { return { ... iconSet: iconSet ... } } } </script>
import React from 'react'; import * as iconSet from '../assets/icon-set' export default class App extends React.Component { render() { return ( <div> <svg className="Icon" aria-hidden="true"> <use xlinkHref={iconSet.Check}></use> </svg> ... </div> ); } }
咱們已經花了大量時間在講 SVG 圖標和 SVG sprite的製做,如何將圖標放到網頁中,接下來將介紹如何經過 CSS 給圖標增長樣式。
咱們能夠在 CSS 經過元素選擇器選中全部的 <svg> 標籤,但若是 SVG 有圖標之外的用途的話,就會出問題,此外FireFox 瀏覽器還存在相關的 bug (下文有相關解釋),因此最好不要這麼作。
而我建議給每一個圖標增長兩個 class 名,一個通用型的 class 如 Icon,一個獨有的 class 如 Icon--arrow。
<svg class="Icon Icon--arrow" aria-hidden="true">
<use xlink:href="/path/to/icons.svg#arrow"></use>
</svg>
咱們推薦使用 SUIT CSS 命名規則(你能夠選擇喜歡的命名風格),相似 class="icon-arrow" 這種,這樣就可使用相似 svg[class*="icon-"] 的CSS選擇器選中圖標。
推薦的默認樣式以下:
.Icon { /* 經過設置 font-size 來改變圖標大小 */ width: 1em; height: 1em; /* 圖標和文字相鄰時,垂直對齊 */ vertical-align: -0.15em; /* 經過設置 color 來改變 SVG 的顏色/fill */ fill: currentColor; /* path 和 stroke 溢出 viewBox 部分在 IE 下會顯示 normalize.css 中也包含這行 */ overflow: hidden; }
上下兩行圖標都用了默認樣式,差異在於父元素的字體和顏色。
當須要定製某個圖標的樣式時,能夠參考下面這段代碼:
.MyComponent-button .Icon { /* 設置寬高 */ font-size: 40px; /* 設置顏色 */ color: purple; /* 可能須要重置垂直對齊 */ vertical-align: top; }
圖標的顏色與父元素的文本顏色相同,若是圖標沒有繼承父元素的文本顏色(currentColor),去看看圖標源碼中是否存在 fill 屬性。
SVG許多樣式屬性都是繼承來的,好比在最外層的 <svg> 標籤,經過CSS設置了 fill 屬性,內層的 <path>、 <circle> 等元素都會繼承該屬性,咱們還能夠在 <svg> 標籤設置其餘CSS屬性,好比 stroke:
.Icon--goldstar { fill: gold; stroke: coral; stroke-width: 5%; stroke-linejoin: round; }
默認樣式和定製樣式的星形圖標
大多狀況下不須要修改太多,只要設置 fill 屬性裏改變圖標的顏色,有時可能會增長或調整下stroke 來加個邊框什麼的。
當一個圖標包含兩個 <path> 時就能夠設置兩種不一樣的 fill 值,即顯示兩種顏色。
<symbol id="check" viewBox="0 0 20 20"> <!-- 繼承 CSS 中設置的 fill 值 --> <path d="…" /> <!-- 繼承 CSS 中設置的 color 值--> <path fill="currentColor" d="…" /> </symbol> .Icon--twoColors { fill: rebeccapurple; color: mediumturquoise; }
還記得前面提到的在圖標四周留白嗎?在用 stroke 時就顯得尤爲重要了。
.Icon--strokespace {
fill: none;
stroke: currentColor;
stroke-width: 5%;
}
在 SVG 中,stroke 在 path 兩側,若是 path 到了 viewport 的邊界,stroke 就會有一半被截斷。
這個例子裏,第一個圖標四周並未留白,第二個四周有 0.5px 的留白(viewport 爲 15px)
如何設置 stroke 的尺寸是個難題,下面這個例子是兩個 stroke-width 爲 1px 的圖標:
stroke-width 的值是跟圖標的尺寸有關,在上圖中:
第一個圖標的 viewBox 的寬高爲20px,因此1px 的 stroke 是圖標尺寸的 1/20,粗細適中。
第二個圖標的 viewBox 的寬高爲500px,因此1px 的 stroke 是圖標尺寸的 1/500,顯得很細。
若是全部圖標的 viewBox 值相同的話,倒不會有什麼問題。一旦它們的寬高差異很大時,使用像素單位或者無量綱量單位(stroke-width:1)就會出問題了。怎麼解決這個問題?
推薦使用百分比,一樣的例子,這回設置 stroke-width:5%:
對於正方形圖標,設置 stroke-width: N% 看起來完美解決問題(注意:在太寬或過高的圖標上可能會不太同樣)。
有些 SVG 並不是圖標,就不用放到 SVG sprite 中,好比說:
不須要修改樣式的 SVG 圖形,直接用在 <img> 標籤裏就行了。
須要增長動畫的 SVG 圖形,考慮將整個 <svg> 標籤做爲內聯元素放入頁面中,這樣就能夠選擇特定的部分或 <path> 增長樣式和動畫了。
注意:若是一個 SVG 圖形大小超過100 x100 ,或者內部有不少元素,就不要把它當作圖標來處理了。
看完前面幾個部分,你已經掌握 SVG 圖標的不少技巧了,接下來是一些的拓展內容。
當樣式文件因爲網絡問題加載失敗時,網頁就失去了樣式,若是網頁內容結構化良好,頁面內容仍然可讀,可是圖標就會顯示成一個龐然大物了。
最新的瀏覽器默認將 SVG 元素顯示成 300x150px,其餘瀏覽器可能會把 width 設置成100%
建議把樣式直接寫到 <head> 標籤裏面。
<style>.Icon{width:1em;height:1em}</style>
在第三部分 將圖標放入網頁 中,咱們提過外部 SVG sprite 能夠延遲加載,由於瀏覽器預加載模塊不會識別處理 <use xlink:href="/path/to/icons.svg#something"></use> 這種形式。
那咱們能夠作點什麼:
標準且前衛的方法:在 <head> 里加一個 <link rel="preload" href="/path/to/icons.svg" as="image"> (有關預加載的細節:支持最新 Chrome,其餘瀏覽器即將支持)。
保守的方法:在 <body> 裏最前面的位置加上 <img style="display:none" alt="" src="/path/to/icons.svg"> 。
我沒有實際測試這些方案,一般來講把內聯和外部 SVG sprite 並用,就已經有足夠的性能表現,已不太須要再去關心預加載,可是偶爾探索下相關知識也不失爲一件好事。
咱們已經學習了定製 symbol 中全部路徑的 fill、stroke ,爲 path 增長多種顏色。可是能夠直接選中特定的 path (使用 class 選擇器)繼而修改樣式嗎?
答案是:能夠,也不能夠。
若是使用了外部 SVG sprite,沒法選中 <symbol> 裏的任何 <path> 和其餘元素。
若是使用了內聯 SVG sprite,能夠選中 <path> 並修改樣式,可是全部地方都應用這些樣式。
因此,即便是內聯 SVG sprite,能夠這麼寫:
#my-symbol .style1 { /* Styles for one group of paths */ } #my-symbol .style2 { /* Styles for another */ }
不能夠這麼寫:
.MyComponent-button .Icon .style1 { /* For 1 group of paths for this icon in this context */ } .MyComponent-button .Icon .style2 { /* For another group */ }
譯者注:.MyComponent-button .Icon .style1
沒法選中 class 名爲 style1 的 path。
除非在火狐瀏覽器離,你能夠輕鬆選中 <symbol> 中的實例,但這是屬於火狐瀏覽器的私有特性,意味着其餘瀏覽器存在着兼容性問題,因此但願火狐瀏覽器能修復這個問題(或者說是 bug)。當新標準來臨時,也許能夠經過 Shadow DOM 來選中,但標準自己也在不斷變化,因此這一點沒法肯定(/deep/ 連結符已被棄用)。
到目前爲止,咱們學習了經過 CSS 繪製單色和雙色 SVG 圖標,那有沒有可能繪製三種、四種甚至更多顏色呢?咱們能夠經過 CSS 變量 (又稱 CSS custom properties)實現,這須要在 SVG 上寫很多東西。
<symbol id="iconic-aperture" viewBox="0 0 128 128"> <path fill="var(--icon-color1)" d="…" /> <path fill="var(--icon-color2)" d="…" /> <path fill="var(--icon-color3)" d="…" /> <path fill="var(--icon-color4)" d="…" /> <path fill="var(--icon-color5)" d="…" /> <path fill="var(--icon-color6)" d="…" /> </symbol>
下面這個 demo 中,是從 Iconic 裏「偷」來了一個圖標,嘗試模仿下 Iconic 中圖標多色效果。
一個 symbol 中使用了 6個不一樣的 CSS 變量(在支持 CSS 變量的 Firefox 、Chrome 或者 Safari 9.1+ 中打開)
上面的例子中只有一個圖標,第一個圖標沒有聲明變量,因此 fallback 成了currentColor,後面兩個圖標每一個都聲明過一套顏色變量,記得在支持 CSS 變量 的瀏覽器中打開下實際效果。
當咱們把 stroke-width 設置爲 N% 時,這個百分比值是根據什麼來定的?是根據圖標的寬度或者高度嗎?根據 官方文檔,實際上是和對角線有關,1% 的值爲:對角線長度除以根號2(接近1.4)後取 1%。
這意味着對於正方形圖標,1% 就等於寬度或高度的 1%,對於較寬或較高的圖標的話結果不太同樣。
第二個圖標的寬高比爲2:1,設置了 stroke-width:5% 後,輪廓的寬度約爲寬度的 7.91%,高度的 3.95%。
整體來講,建議把 stroke-width 的值設爲百分比。若是你在使用方形的話,那麼1%約爲圖寬度的百分之一。
有沒有可能使用 gradient 設置 fill 值呢?事實是不能,CSS的 linear-gradient() 產生的是一個圖片值,而 fill 屬性是不接受圖片值的。
SVG 的編碼及使用 gradient 有其特定語法,但跟我們討論的主題(SVG 圖標)關係不是很大,能夠嘗試下,可是這得花功夫,並且至少得硬編碼進入一些參數,有興趣的話能夠嘗試下。
爲了不出現頁面未加載樣式時,部分圖標顯示巨大的問題,咱們給 <svg> 設置 width 、height 屬性。
<svg width="20" height="20"> <use xlink:href="…"></use> </svg>
接着咱們在 iOS 的 Safari 測試下,有一半 SVG 圖標掛了?什麼鬼?!
實際上,Safari/WebKit 不支持先給 SVG 設置寬高屬性,再經過 CSS 去改變尺寸的,特別是想把圖標變小時,圖標的容器會變小,但圖標的內容並不生效。
咱們的解決方案是移除 SVG 上的 width 、 height 屬性,只經過 CSS 控制圖標尺寸。最新的 Safari 已經修復了這個問題(Safari 9.1 桌面版和 iOS 9.3)。
若是你想要設置背景色、邊框、內邊距等,你應該往圖標的父元素上增長樣式,而不是圖標自身的<svg> 標籤,雖然看起來最新的瀏覽器上都沒有問題,可是老版本 WebKit 瀏覽器上渲染存在問題,所以建議在圖標外面包一層,好比 <span>、 <button>、 < a >等。
但老版本 WebKit 瀏覽器渲染會有點誤差。Firefox:避免使用 svg 做爲元素選擇器
爲何呢?當咱們使用 <use> 標籤時,瀏覽器會建立 Shadow DOM 去複製 <symbol> 中的內容,看下來就像這樣:
<svg class="Icon Icon--something" aria-hidden="true"> <use xlink:href="#something"> <svg viewBox="0 0 20 20"> <path d="…" /> </svg> </use> </svg>
以前的部分提到過,Firefox 瀏覽器目前支持選中 <use> 標籤建立的 Shadow DOM 中的內容,因此若是寫了這樣的 CSS:
svg { fill: red; } .Icon--something { fill: green; }
在 Firefox 瀏覽器中就會變成相似這樣:
<svg class="Icon Icon--something" aria-hidden="true" fill="green;"> <use xlink:href="#something"> <svg viewBox="0 0 20 20" fill="red;"> <path d="…" /> </svg> </use> </svg>
圖標在其餘瀏覽器中是綠色的,可是在 Firefox 瀏覽器中會是紅色,由於內部的 <svg> 標籤按照 CSS 第一行中的 fill: red 去渲染。
還有一種寫法能夠避免:
:not(use) > svg { … }
文章轉自:https://zhuanlan.zhihu.com/p/...
英文原文:https://fvsch.com/code/svg-ic...