SVG图标 – 踩过的坑

1. Safari SVG bug
Safari浏览器对svg fragment identifier的支持不好,即在动态环境下(server上)使用img标签访问name.svg#frag_id不会得到预想的结果(本地静态文件访问没有问题),目前仅sarafi7支持。这就意味着如果使用svg sprite,并且需要兼容safari,那么不能使用img标签,如下图。
两种解决方法,一种使用和img类似的embed或object标签,另一种是使用svg symbol内联形式,我更推荐后者,它不仅可以方便控制svg图标,而且兼容ie9+。

2. svg对齐
在svg图标右侧经常会有文字说明,而svg标签默认的vertical-align是baseline,就会造成文字偏下,如下图左,解决方案为将vertical-align设置为middle,如下图右。

3. 内联svg无法修改颜色
众所周知使用内联svg图标可以修改颜色和尺寸,如下


但是,有时候开发者会发现使用fill或者sroke不起作用,无法修改填充色或者边框色,这是因为svg图标已经添加了fill或者stroke属性,大部分情况下是设计人员导出svg图标的问题,有意无意附上了fill/stroke属性,如下svg文件,它就不能使用fill修改颜色。

4. 传统方式使用svg图标的缺陷
使用传统的方式,包括img,background,甚至view(fragment identifier)和stack,都是无法通过fill,stroke,svg filter去修改它的样式,原因在于svg的属性不能通过class改变,必须通过在标签上增删属性实现(e.g. <path fill=”red” stroke=”grey”….)。所以推荐使用内联svg标签,如果非(jue)要(jiang)使用img等,可以通过如下三种方式修改:
    1. 使用js获取svg dom,直接增删属性
    2. 使用css3 filter修改
    3. 针对不同颜色,大小制作多个svg图标(最简单粗暴)

5. svg use浏览器兼容性
svg use标签是不兼容IE 13以下所有的浏览器的,可以使用polyfill svg4everybody or svgxuse解决

SVG图标 – 踩过的坑

web图标技术简史

在计算机科学中,图标(icon)是用于导航目的的象形图,一般是一些尺寸很小(例如48*48)的图片,例如windows中的“我的电脑”。而在网页开发中,图标具有更广泛的作用,它可以是具有交互功能的导航按钮,增加页面美观,提高页面可读性,还可以通过动画效果使页面更加炫酷,吸引聚焦更多客户。

从传统图片形式的图标,到现在矢量图形式的图标,再到通过css直接绘制的图标,图标技术大概经历如下三个大的阶段:

1. 以png为主导的图片形式的图标
在IE统治的网络世界里,图标都是由图片实现的,这样就造成一个网站包含大量的图片(虽然早期的网站本身就充斥着大量的大图片,相比而言图标都不算什么),这样不仅增加网络请求数量,而且增加网页体积,降低加载速度,更甚之还会遇到ie6 透明度bug
另一方面,对比jpg和png图片,png虽然是无损格式,但由于它在各类浏览器中支持较好,而且对于简单色彩的图片和文字图片,它的体积比jpg还要小,所以对于图标的实现,png格式应用更为广泛。
最后,在没有CSS3的那些年里,甚至当前“偷懒的人”,想实现兼容ie的带有阴影,渐变及特殊形状等的图标,png图标还是部分被采用的。

2. 以font为核心的字体形式的图标
互联网的发展促使网页应用需要更好的用户体验,也就需要大量简约,统一,美观的图标,字体图标就是伴随着社交网络和CSS3而出现兴起的。它的实现基于font face和字体文件集,包括eof,ttf及woff等。
相比传统图片图标,它是矢量图,可以方便的缩放尺寸;它本质还是字体文件,也就可以使用css font相关属性实现各种效果,例如颜色,阴影等;它还有很好的性能表现,因为字体文件通过一次请求就可以获得,就像图标的sprite技术。这样就避免了到处搜罗各种图片,只需要一个规范统一的字体文件集合,目前最流行的当属font awesome。
需要提一下字体文件,eof和ttf字体是老的字体格式,eof仅为兼容ie而存在,ttf的版权问题而被抛弃,woff是目前的主流格式,如果只兼容现代浏览器或者高版本ios/android,只需要woff就够了。
当然,它的缺点在于兼容性(虽然现在逐渐可以忽略),例如ie8它需要提供html5js shim,同时它还有定位不准,可读性差,与表情冲突及不适合做复杂图标等缺陷。最后,定制化字体图标相比会复杂,不过大量iconfont生成网站和插件在一定程度解决了这个问题,例如font custom

3. 以svg为代表的矢量图形式的图标
svg是与woff同时出现的业界推崇的图标实现,apple很早就开始使用svg图标。
和字体图标一样,svg也属于矢量图标,所以它的体积小,控制灵活且扩展性好。相比字体图标会有定位不准确问题,svg图标可以精确定位,并且可以无损缩放到retina屏幕上。和字体图标相比,svg是图形,不是字体,所以它没有锯齿问题,还可以使用多种途径显示,包括背景图,img标签以及内联直接插入html,尤其内联是目前比较流行的方案,它就像html一部分,减少网络请求。不像单色的字体图标,svg是多色的,可以实现更漂亮,更丰富,更像传统图片但各方面都优于他们的图标集合。
svg图标的缺点包括ie8兼容性,图标体积随图标复杂度非线性增大,而且它的原子性决定不能像普通图片一样显示部分内容。

4. sprite
Sprite是为解决网页图片过多造成的服务器请求压力而提出的,基本思想就是将所有图片放在一张大图上,通过css 定位所需要的图片。它不是新技术,早期的网站开发大量使用sprite,很多实现渐变效果的线条,背景色,hover切换都会放在一起,如下图是两个典型的例子,一般由人工摆放。


它还可以用在动画实现上,配合js或css3 animation可以很简单的实现动画效果。
除了字体图标,无论图片还是svg,为了增加网页性能,减少请求数量,都是需要sprite技术的,例如svg_sprite,它可以自动生成svg sprite,以及相应css文件甚至demo,还支持多种模式包括view,defs,symbol及stack等。

5. CSS3样式图标
CSS3图标并非主流,仅用在对图标需求量不大,并且图标相对简单的场景下,例如箭头,对勾等,而且由于它完全由CSS3画出来的,存在兼容性问题。这里有一些不错的CSS图标,可以激发用CSS绘制图标的灵感。

相关链接:

web图标技术简史

SVG图标 – 基础篇

1. svg作为背景
用法同普通图片,大小缩放由元素的width/height和background-size属性一起实现。

2. svg作为img前景
用法同普通图片,使用width和height缩放图片。

3. 使用svg defs
以上两种方式都是直接外部引用(external)svg文件,下面两种方式defs和symbol属于内联引用(inline)svg元素,既可以通过路径指定svg文件,也可以直接将svg代码放入body中。

内联引用demo
定义在defs中的元素的作用是为以后的引用,所以它们是不可见的(invisibility),只有通过use元素才能访问。需要注意的是,内联型定义defs的svg元素需要隐藏,否则在页面会留白,因为svg本身会占用空间,例如下面demo中将svg的wdith和height设置为0,position设置为absolute,当然直接display为none也可以。

外部引用demo
大部分情况,为了所有页面共享,会将defs定义放在一个单独的文件。它需要注意的是,svg标签不需要隐藏,但必须有w3c的命名空间声明,否则use无法找到相应图标。

4. 使用svg symbol
symbol用于定义可以多次引用的图形模版,并且可以为其添加语义和结构,使用上和defs很类似。它们的区别在于viewbox可以直接定义在symbol标签上,而且symbol可以有自己的desc和title,增强可读性,所以目前对symbol的支持超过defs。

 


5. 使用view定位svg
view更像一个虚拟的空间,在view中定义viewbox可以指定显示图形区域。
从下面的demo可以看出,每个view在svg图形中“圈”出一块小区域,代表一个icon。

6. svg stack技术
设计师总是在寻找用最小的空间摆放更多的图标,而这个可以通过svg堆叠实现,这点普通图片是做不到的。从上面的demo可以看出,两个heart图标是非叠加并列的放在一起的,假如有100个图标,应该是很大的一个文件,而在svg中这些图标可以交叉堆叠在一起,如下图,但带来的问题就是文件的可视化,不能直观的找到和看到图标。

为了把普通svg改造为stack,需要两步,首先通过viewbox改为一样而将所有图标堆积在一起,然后通过样式隐藏所有图标,只有:target元素显示。

DEMO下载链接: svg demo

SVG图标 – 基础篇