amfe / article

7.58k stars 1.07k forks source link

Web中的图标 #2

Open airen opened 9 years ago

airen commented 9 years ago

随着时代的变迁与技术的不断的更新,在当今这个时代,Web中的图标(Icons)不再仅仅是局限于<img>。除了<img>直接调用Icons文件之外,还有Sprites(俗称雪碧图)Icon Font(字体图标)SVG Icon等等。今天我们就来一起探讨一下这些方法在Web中实现Icon的利弊。

思考变革

设计师不管分辨率(Resolution independent)和设备平台,其追求像素完美(Pixel Perfection)、体验一致性;而前端工程师们更为关心的是页面的可访问性(Accessability)、性能以及重构的灵活性,可复用性,可维护性等等。

而当下这个互联网时代,设备多样化,显示分辨率层出不穷,对于Web前端工程师来说可是灾难性,而且碰到的难题也是越来越多:

前途是光明的,道路是曲折的。前端工程师一直以来就是见招拆招,从未停止过自己向前的步伐。不信我们一起来看。

原始的<img>

<img>标签,大家都知道是用来给Web页面添加图片的。而图标(Icons)其实也是属于图片,因而在页面中可以直接使用<img>标签来加载图标。并且可以加载任何适用于Web页面的图标格式,比如:.jpg(或.jpeg)、.png.gif。对于今天的Web,除了这几种图片格式之外,还可以直接引用.webp.svg图像(图标)。

优势

看上去这都不是什么优势,我也只能为其想到这两条了。

劣势

虽然img可以帮助前端工程师往Web页面中添加需要的图标,但其不足之处也是众所周知的。由于img的局限性与不足,2004年3月@Dave Shea提出了一种全新的技术CSS Sprites(在国内常常将这种技术称为CSS雪碧,又称CSS精灵)。

CSS Sprites出现之后,很多互联网团队都在使用这种技术,比如:

Amazon

Amazon

YouTube

YouTube

Google

Google

Facebook

Facebook

Yahoo

Yahoo

当然,国内使用CSS Sprites也不少:

淘宝

淘宝

新浪微博

新浪微博

诸如此类的还很有很多。

在此对于CSS Sprites的技术就不做过多的阐述,如果您想了解这方面的相关知识,可以阅读下面的文章科普:

早期CSS Sprites使用的都是位图,而且为了适合Web页面使用环境,采用的都是.png文件格式,但在现在只使用位图,会受到很多的限制,比如在Retina屏下,位图会模糊。也就是说,为了适配各种终端设备分辨,CSS Sprites不在局限于位图,也可以将SVG这样的矢量图集合在一起。其和位图最大的不同之处可以根据设备分辨率,调整Sprites的尺寸,从而不影响图标在设备的呈现质量

相对而言,SVG更适合当前的Web页面,当然,这种技术也受到一定的局限性,比如说修改ICON图标颜色之类,就必须去修改.svg文件,这对于前端人员来说是无法接受。有关于SVG Sprites相关的介绍,可以阅读下面相关文章:

虽然CSS Sprites有其足够的优势,而且众多开发者都在使用这种技术,但是到了今天,不得不对CSS Sprites说再见(其实是跟位图的图标说再见)。

随着Retina屏幕的出现,大家都发现自己在Web中使用的图标变得模糊不清,直接拉低了自己产品的品质。对于Web前端人员也必须面对考虑各种高清屏幕的显示效果。由此也造成同样的前端在代码实现的时候需要根据屏幕的不同来输出不同分辨率的图片。不管你采用的是何种手段:

不管使用哪种方法,都不是一件易事,比如使用image-set和媒体查询,只适合背景图像;而对于srcsetpicture方法仅适合Web引入图像的情景。而且这些方法直到目前为止在浏览器上都受到了很多的限制。

为了解决屏幕分辨率对图标影响的问题,字体图标(Icon Font)就顺势而生了。字体图标是一种全新的设计方式,更为重要的是相比位图而言,使用字体图标可以不受限于屏幕分辨率,冲着这一点就具有非常强的优势,而且字体图标还具有一个优势是,只要适合字体相关的CSS属性都适合字体图标,比如说:

基于这些原因,现在Web开发中,使用字体来制作图标的应用也越来越多。

优势

为了适配各种分辨率,让图标显示更完美,除了字体图标之外,还可以使用SVG图标。SVG图标是一种矢量图标。其实回过头来看,字体图标其实也是使用SVG封装过的。

为什么要使用SVG图标

SVG图标实际上是一个服务于浏览器的XML文件,而不是一个字体或像素的位图。它是由浏览器直接渲染XML,在任何大小之下都会保持图像清晰。而且文件中的XML还提供了很多机会,可以直接在代码中使用动画或者修改颜色,描边等。不需要借助任何图形编辑软件都可以轻松的自定义图像。除此之外,SVG图像也有过字体图标的一个主要优势:拥有多个彩色图像的能力。

优势

为了让图标能更好的适配各种屏幕分辨率,大家首先的就是字体图标和SVG图标,那么这里为何又要谈:为什么要使用SVG图标替代字体图标@Chris Coyier的《Inline SVG vs Icon Fonts》(中文译文可以点击这里阅读)和@Ian Feather的《Ten reasons we switched from an icon font to SVG》(中文译文可以点击这里阅读)。

字体图标 vs SVG图标

字体图标 SVG图标
图标是矢量 浏览器会以字体解析它,所以浏览器会以文字的方式来对图标做抗锯齿处理,这可以导致字体图标没有期待中的那么锐利 SVG是XML文件,浏览器直接解析XML文件,直接就是矢量图形,图标锐利,体积也小
可控制性 可以通过font-size、color、text-shadow等CSS来控制图标 除了字体图标一样的CSS控制方法之外,还可以单独控制一个复合SVG图标中的某一部分,也可以给图标描边
控制图标位置 图标位置会受到line-height、vertical-align、letter-spacing等属性影响 SVG图标的大小就是很精确的SVG图形的大小
图标加载 跨域时没有合理的CORS头部、字体文件未加载、@font-face在Chrome中的bug和不支持@font-face的浏览器等,这些原因都会造成字体图标渲染失败 SVG图标就是文档本身,只要支持SVG的浏览器,都能正常的渲染
语义化,易访问性 为了更好的显示图标,通常使用伪元素或伪类来做,这样做语义化较差 SVG图标就是一个小图片。SVG的语义就是”我是一张图片“,感觉可能更好
易用性 使用一个已造好的字体图标集从来都不有效,因为有太多的图标未使用。而创建一个你自己的字体图标集也不是轻松的事情,需要懂得相关的编辑工具或应用软件 SVG图标会简单一些,因为你可以自己手动地操作,如果需要的话,你可以使用相关的编辑工具
浏览器支持度 得到非常好的支持性,可以一直支持到IE6,在Opera mini,Android 2.1,Windows Phone 7.5-7.8没到支持 浏览器支持性一般,IE8和Android 2.1以及其以下浏览器不支持。不支持可以采用降级处理,但不并完美

DataURI

DataURI是利用Base64编码规范将图片转换成文本字符,不仅是图片,还可以编码JS、CSS、HTML等文件。通过将图标文件编码成文本字符,从而可以直接写在HTML/CSS文件里面,不会增加任何多余的请求。

但是DataURI的劣势也是很明显的,每次都需要解码从而阻塞了CSS渲染,可以通过分离出一个专用的CSS文件,不过那就需要增加一个请求,那样与CSS Sprites、Icon Font和SVG相比没有了任何优势,也因此,在实践中不推荐这种方法。需要注意的是通过缓存CSS可以来达到缓存的目的。

优势:

不管使用哪种方案来制作Web页面的图标,大家都会比较关心其对页面的性能有多大的影响。在这里提供一个测试用例,在这些用例中,页面加载了28232 x 32的图标。

Web Icons

这些图标直接通过IcoMoon APP获取。并且分别采用了img加载.png、CSS Sprites(png和svg的Sprites)、字体图标和SVG图标的方式写的用例:

具体代码就不做演示,接下来通过在线性能测试工具WebPageTest(除了这个在线测试工具之外,还可以点击这里获取其他的在线测试工具)来做一个简单的测试。当然这样的测试可能不会非常的准确,但或多或少能从相关的数据上向大家形象的展示不同的方案对页面性能的影响会有多大。

特别声明:以下提供的测试数据受到网络直接影响,仅提供做为示例参考。

PNG/SVG文件

PNG/SVG文件

页面使用<img>加载了282.png.svg图标。每个图标的大小是32px x 32px

PNG Sprites

PNG Sprites

282.png图标集成在一个Sprites文件中,Sprites图片文件大小是108kb

SVG Sprites

SVG Sprites

282.svg图标集成在一个Sprites文件中,Sprites图片文件大小是180kb

SVG

SVG

在页面中直接使用SVG源码制作的图标。

Icon Font

Icon Font

使用Font制作的图标。

以上图表中的数据仅做参考,因为在线测试,网速之类直接影响到测试结果。熟悉性能测试的同学,可以直接在本地测试用例,拿到更具有价值的参考数据。也希望同学能将这方面的结果在评论中与我们一起分享。

如何选择

前面介绍了Web中制作图标的几种常见方案,每种方案都有其自己的利弊。那在实际中要如何选择呢?这需要根据自身所在的环境来做选择:

当然,在实际开发中,可能一种方案无法达到你所需的需求,你也可以考虑多种方案结合在一起使用。

总结

全文主要介绍了Web中图标的几种方案之间的利与弊。相对而言,如果不需要考虑一些低版本用户,就当前这个互联网时代,面对众多终端,较为适合的方案还是使用SVG。不管是通过img直接调用.svg的文件还是使用SVG的Sprites,或者直接在页面中使用SVG(直接代码),都具有较大的优势。不用担心,使用的图标在不同的终端(特别是在Retina屏)会模糊不清。而且SVG还有一个较大的优势,你可以直接在源码中对SVG做修改,特别是可以分别控制图标的不同部分,加入动画等。

当然,你或许会有众多的顾虑,不懂SVG的怎么破,就算不懂SVG,你也可以借助SVG的图形编辑软件或者工具,来协助你。除此之外,除了这些方式在Web中嵌入图标之外,对于一些简单的小图标,可以考虑直接使用CSS代码来编写,这种方式可能较为费时费力,但其具有的优势,我想大家都懂的。

最后非常感谢您花时间阅读这篇文章,如果您有更好的思路或建议,非常欢迎在下面的评论中与我一起分享。

hongru commented 9 years ago

长文...哈哈。看最后的总结瞬间就清晰作者的立场了@airen

fakefish commented 9 years ago

终于看完了,还是蛮有收获哒~

Krispomoho commented 9 years ago

是时候用一波svg了

dolymood commented 9 years ago

flyyang commented 9 years ago

能不能不要回复顶,赞这些东西。有能力就交流,没能力就观察,最好不要干扰大家的时间线吧...

WihteCrow commented 9 years ago

我感觉现在PNG Sprites已经过时了,除非特殊情况下。无论使用 IconFont 还是 svg都是一种对页面展示的追求

satlxq commented 9 years ago

PNG Sprites 在移动设备上是有点慢的,无论从体积还是解码速度上来看,是时候更换下技术了。 Android 2.1 的占比其实已经很低了

ikeepf commented 9 years ago

给个赞!之前移动端开发烦人的背景图模糊问题终于有解决办法了!

dolymood commented 9 years ago

支持 SVG Sprites ,参照 zhangxinxu 大神的文章,以及大神对应的工具页面,针对 illustrator 软件生成的做的二次处理,写了一个node版本的 https://github.com/dolymood/aisvg2sprite 欢迎试用

stanleyxu2005 commented 9 years ago

DataURI其实不错,撇除老的桌面系统(ie兼容),这个最轻量,而且可以内联到css的规则里面。 可以设计的时候是图片,发布的时候用工具自动转换成DataURI。唯一缺点是,上线之后想修改,显然无法徒手了。

leungwensen commented 8 years ago

使用SVG图标不用担心“需要了解使用制作软件绘制SVG图形或专业的SVG图形编辑软件”这个问题了!我把大部分流行的iconfont都转换成了SVG,可以直接按需选择、下载SVG sprite文件了。 http://leungwensen.github.io/svg-icon/

Hideer commented 6 years ago

就目前来说png sprites+字体图标能够满足绝大多数公司的开发哦 ~