SVG Sprite(這裏特指基於svg symbol)做爲傳統css sprite和icon font的替代方案,在現代瀏覽器(ie9+)上可以正常運行,關於它的技術背景、特色和降級方案等再也不贅述,能夠參考如下幾篇文章,寫的都很是不錯:javascript
面向將來的圖標圖片精靈jquery
在具體實踐過程當中,遇到如下兩個問題:css3
IE瀏覽器不支持外鏈svg sprite文件,也就是說svg sprite必須嵌入到頁面裏面(最前面)git
IE瀏覽器下,擁有use標籤到svg元素上到點擊事件沒法冒泡,現象是在使用代理的方式綁定事件時(綁定到svg元素的父元素上,綁定到svg元素自己就更沒辦法了),點擊svg元素自己沒法觸發點擊事件。github
下面就這兩個問題逐個看看解決方案。gulp
咱們一是要保證ie下svg sprite圖標能正常顯示,因此必須採用嵌入到頁面的方案,同時還要解決緩存的問題,若是直接放在模版文件裏,那每次都須要從新下載,就失去了原來css spirte和icon font能夠緩存的特色。瀏覽器
這裏我採用的方案是本地利用構建工具(我用的是基於grunt的grunt-svg-sprite,gulp也有對應的插件)生成svg sprite文件,而後單獨在頁面最前面放一個js文件,js文件包含svg sprite的內容,並在自身加載完成後把svg sprite插入到頁面最前面。
tpl:
<body> <script type="text/javascript" src="/static/js/svgsprite.js" async></script> ... </body>
svgsprite.js:
// 構建工具生成的svg sprite文件 var svgsprite = require('./svg/symbol/svg/sprite.symbol.svg'); document.body.insertAdjacentHTML( 'afterBegin', // 插入body第一個子節點前面 '<div class="hide">' + svgsprite + '</div>' );
browserify配置:
// 是svg文件能夠做爲string類型被require brs.transform(stringify(['.svg']));
由於js文件是能夠緩存的,因此至關於變相把svg sprite緩存起來了。
第二個問題比較棘手一點,關於這個問題,jquery開發人員也作了解答:
Delegated event not firing for click within SVG use element
前面說了是因爲包含use標籤的svg元素沒法冒泡,那麼直接在svg元素或者svg父元素上綁定事件就能夠了,可是在涉及新增、刪除等操做時,可操做的按鈕都是動態添加的,若是每次添加元素都要從新綁定事件,是很是麻煩的。
幸虧有pointer-events
這個神器,這是css3的新屬性,雖然對於普通html元素的支持性不是太好,但對於支持svg的瀏覽器,基本都支持這個屬性。
http://caniuse.com/#search=pointer-events
Already part of the SVG specification, and all SVG-supporting browsers appear to support the property on SVG elements.
經過對svg元素應用pointer-events:none
,可讓svg相對點擊事件「透明」,只要事件綁定到svg的父元素上,且父元素具有寬高(須要設置爲inline-block,或者應用float、position:absolute等,不然ie下點不中)。
針對以上需求,我寫了個簡單的sass mixin:
@mixin svg-sprite( $width, $heigth, $fill: default, $hover-fill: default ) { display: inline-block; width: $width; height: $heigth; svg.g-ico { width: $width; height: $heigth; pointer-events:none; } @if $fill != default { svg { fill: $fill; } } @if $hover-fill != default { &:hover { // tips: hover是在父元素上 svg { fill: $hover-fill; } } } }
給svg元素的父元素應用這個mixin,這樣就算是圓滿解決了這個問題。
Tips: 由於咱們的網站兼容ie9+,因此ie9如下的沒有作降級處理,若是須要,能夠參考前面列出的幾篇文章。