这是CSS技术和SVG技术对比系列教程中最后一篇。本文选取了几个CSS和SVG的解决方案,而不是一个解决方案------使用CSS和SVG实现。有关于解决方案的每个细节已经有很多这方面的优秀文章。
让我们先从CSS和SVG最具争议的主题开始:图标系统。
字体图标 VS. SVG图标
在我的印象中,我个人使用字体图标只用过两次,都是在客户端项目中使用的。我从来不觉得他们直观。
使用字体图标不具语义化:一个图标是一个图像或数字,而且字体图标一般都使用空的<div>
或<span>
标签,配合伪元素的content
属性。
字体图标是单色的,不能实现多色图标,除非你使用多个元素拼合在起,然后为每个形状使用不同的颜色,从而构成一个完整的图标。虽然想出这个解决方案的人来说很聪明,但略显多余,至少我是这样看的。如果你对这个解决方案感兴趣,可以看看Parker Bennett写的一篇博文,这篇文章就是介绍如何通过多个元素构建一个彩色的图标。
扩展阅读
字体图标在很多浏览器上也会奇怪的失败、有锯齿等问题,常常要用反锯齿样式让他们看起来不那么锋利,这是多么令人烦恼的一件事情。
Chris Coyier在CSS-Tricks上专门写了一篇有关于字体图标和SVG图标之间的利弊,以及CSS怎么来显示。如果你对此感兴趣,可以点击这里阅读。
这里总结了一些有关于SVG图标的优点:
-
SVG更具语义化,SVG图标就是一个图标标记
-
SVG在所有屏幕分辨率下都能渲染的清晰,看起来干净利落
-
SVG图标能更好的控制图标样式(比如说彩色图标)。可以选择在SVG中设置或使用CSS样式来控制。当然有一些限制,看取决于你是如何嵌入SVG,但这将来或许会有所改变。
-
SVG图标还可以做动画交互效果。图标改变形状时可以具有动画效果
-
你可以使用PNG图为SVG图标作降级处理,让不兼容SVG的浏览器能显示PNG图标
-
SVG图标具有较好的浏览器兼容性,在支持SVG的浏览器下能显示出一样的效果
-
SVG更易创建、嵌入和维护
-
SVG更具可访问性。SVG带有可访问性元素,改善其内容的可访问性。你可以在这里了解更多有关于这方面的知识。
有几种方法可以使用SVG Sprites创建SVG图标系统,让浏览器支持变得更具可靠性。在使用这种技术时,还有一两个Bug。不过我强烈建议你阅读这方面的文章,甚至可以尝试一下。
扩展阅读
图表
引入新的技术来创建图表, 这变得更佳有趣。下面我们深入来看看。
CSS制作图表
使用CSS创建的普通矩形和圆形等形状,可以创建一些简单的图表。
因为CSS创建矩形是非常强大的,只使用CSS来制作图表,最好的一个示例就是创建水平或垂直的矩形图表。
Eric Meyer在很久以前就使用CSS创建了竖线的概述图效果。在他的这篇文章中,他解释了如何使用CSS创建条形图形和使用一个HTML的<table>
元素来给图表标记数据。Eric Meyer介绍的技术是强大的,因为数据采用了语义化的标签来标记(<table>
用来存储数据,可谓是最完美的方式),而且数据可以使用服务端动态插入,比如说PHP语言。
Robin Rendle在Eric的技术上创建一了种新的条形图表,他们使用了相同的原则和CSS技巧。下面的标记就是来自于Robin Rendle的文章:
<table id="q-graph">
<caption>Quarterly Results</caption>
<thead>
<tr>
<th></th>
<th class="sent">Invoiced</th>
<th class="paid">Collected</th>
</tr>
</thead>
<tbody>
<tr class="qtr" id="q1">
<th scope="row">Q1</th>
<td class="sent bar"><p>$18,450.00</p></td>
<td class="paid bar"><p>$16,500.00</p></td>
</tr>
<tr class="qtr" id="q2">
<th scope="row">Q2</th>
<td class="sent bar"><p>$34,340.72</p></td>
<td class="paid bar"><p>$32,340.72</p></td>
</tr>
<tr class="qtr" id="q3">
<th scope="row">Q3</th>
<td class="sent bar"><p>$43,145.52</p></td>
<td class="paid bar"><p>$32,225.52</p></td>
</tr>
<tr class="qtr" id="q4">
<th scope="row">Q4</th>
<td class="sent bar"><p>$18,415.96</p></td>
<td class="paid bar"><p>$32,425.00</p></td>
</tr>
</tbody></table>
使用CSS给表格单元格定位之后,你最终可以看到下图的效果:
具体示例如下:
在他的文章中,Robin还使用相同的原则,创建迷你图表,具本的细节,可以阅读相关文章。
前面介绍的都是使用CSS创建矩形的柱形图表,其实CSS也可以创建饼图。
Lea Verou在CSS技术上具有极高的水平,也想了一个聪明的方式,使用伪元素来和CSS的旋转来创建 两色的饼图。在这篇文章中她详细介绍了有关于这方面的技术。
使用伪元素和CSS的transform
创建一个饼图。上图中虚线的矩形就是伪元素在其父容器中做圆形旋转。
Lea的技术能让你创建像上图所示的双色饼图效果,但是,如果要创建更多颜色的饼图就不是那么容易的事情了。
借Lea的一篇文章来做介绍,使用conic-gradient
可以实现多色饼图。具体如何实现,本文不做过多阐述,如果你对这方面的技术感兴趣,你可以看看Lea写的相关教程。
上图就是conical-gradient
的一个示例截图。另外提供@一丝姐姐下面的案例:
使用conical-gradient
,你想要多少颜色的饼图都可以创建。
此外,一旦
attr()
函数在CSS Values Level 3得到广泛支持,将来只要在一个HTML元素上控制其百分比就可以实现多色饼图:background: conic-gradient(#655 attr(data-value %), yellow green 0);
另外可以使用下面的方法来实现三中颜色的饼图,也是较为容易background: conic-gradient(deeppink 20%, #fb3 0, #fb3 30%, yellowgreen 0);
---Lea Verou
尽管浏览器现在还不支持conic-gradient
属性,但Lea写了一个Polypill库,你现在就可以使用他们。如果你感兴趣的话,一定要自己动手尝试一下。
尽管使用CSS也可能制作出折线图,但我强烈反对使用,因为他们既不方便而且也不是一个表示数据的好方法。
扩展阅读
SVG图表
当涉及到创建图表和数据可视化时,SVG胜过其他技术,包括CSS。
SVG图表和数据可视化访问可以充分互动。SVG不规则的形状是一个完美的效果,而且数据可视化效果可以通过这些不规则形状更好的展示出来。
HTML5 Canvas也可以用来做数据可视化,但是Canvas不是DOM的一部分,因此屏幕阅读器无法访问。你需要在<canvas>
标签中创建一个备用访问内容。你需要采用额外的措施将内容映射到画布上,这样屏幕阅读器才能知道元素之间的相互作用。所以一个HTML5 Canvas需要维护双倍的数据。
使用SVG,语义化强和更具可访问性,而且可以结合JavaScript做交互效果。
条形图可以很容易的使用SVG的<rect>
和<line>
实现,而数据也可以使用<text>
元素,而不需要为内容另外准备一张图。
然而,你可能会不想手动创建这些图表,特别是复杂的数据图表,或者需要动态的交互效果的图表。这个时候你就可以使用D3.js这样的框架了。
D3是Data-Driven Documents的简写。是一个数据可视化的JavaScript库。D3可以帮助你使用HTML、SVG和CSS将数据完整的在现代浏览器展示。
D3可能是最受欢迎的数据可视化操作的一个库,有大量的文章和书介绍如何使用D3。这里有些资源供你参考:
当你使用SVG创建一个简单的饼图时,不需要使用D3这样的库,特别是你的饼图是简单的、静态的,而不是动态的。
Lea在Smashing Magazine上有一篇文章详细介绍 了SVG技术和CSS技术创建一饼图的对比,而且她还想出了一个更实用的SVG技术。使用SVG中的heavy/thick
描边来做圆形。
下图展示了如何使用SVG中的stroke
和stroke-dasharray
属性实现的饼图效果过程:
配合一些JavaScript,你可以动态的看到stroke
创建饼图的整个过程。
Robin Rendle也在CSS-Tricks上写过一篇使用SVG创建图给的文章。
折线图,地图等,都可以使用SVG来创建。SVG将成为制作数据可视化的最佳工具,也可以做出很多好看的图表。
话又说回来,你可能想避免使用SVG、HTML5 Canvas或者WebGL来制作复杂的数据可视化图表,那么你将需要使用成千上面的DOM元素,而且这种情况下制作也是非常的麻烦。至少到现在很少有人会这样去做。另外SVG制作超复杂的数据可视化图表时,需要很多的DOM节点,在这样的场景之下,HTML5 Canvas的性能要比SVG性能略强一些。所以你应该在合适的场景使用合适的技术,做出明智的选择。
Elastic UI互动
在一些地方,CSS不能像SVG一样创建不规则的UI形状和动画,这或许也是SVG最强大特性之一。
下面的示例是@Mary Lou在Codrops写的一个幻灯片的效果:
幻灯片使用了SVG的path
,并且给播放幻灯片时添加了一个路径动画效果。
下图展示了动画中用到的三个路径形状:
使用JavaScript,你可以定义这些路径形状:
// …
// path definitions
paths : {
rect : ‘M33,0h41c0,0,0,9.871,0,29.871C74,49.871,74,60,74,60H32.666h-0.125H6c0,0,0-10,0-30S6,0,6,0H33’,
curve : {
right : ‘M33,0h41c0,0,5,9.871,5,29.871C79,49.871,74,60,74,60H32.666h-0.125H6c0,0,5-10,5-30S6,0,6,0H33’,
left : ‘M33,0h41c0,0-5,9.871-5,29.871C69,49.871,74,60,74,60H32.666h-0.125H6c0,0-5-10-5-30S6,0,6,0H33’
}
}//…
至于动画效果,你可以使用Snap.svg这样的库,幻灯片动画效果选择的是:
// change svg path on entering slide to "curved"
var currItem = this.items[ this.curr ];
currItem.querySelector('path').setAttribute( 'd', dir === 'right' ? pathCurvedLeft : pathCurvedRight ); // morph svg path on entering slide to "rectangle"
setTimeout(function() { currItem.path.stop().animate( { 'path' : pathRectangle }, speed * 3, mina.elastic ); }, speed * .5 );
上面的代码只是部分演示如何简单定义动画路径,如果你要完整的看到示例的效果,要确保你的代码是完整的。
有人可能会认为,上面的效果应该使用CSS。但是,就算CSS的clip-path
可以裁剪出不规则的形状,他们目前仍依赖于SVG创建复杂的形状。所以上面的示例中的形状,不可能使用的是CSS。
我们来看@Mary Lou写的第二个示例:
点击按钮时侧边栏菜单的边框有一个弹性的效果,到目前为止还无法在CSS中画一条这样的线。
在Codepen上能找到很多有趣的SVG动效果案例,下面展示的效果就和上图有点类似:
其他动画效果
尽管使用CSS的filter()
可以创建一些特定的效果,但是SVG的内置filter
具有更多的功能,可以做出更复杂的效果,而且做出来的效果非常吸引人。
Lucas Bebber一直致力于SVG制作的神奇效果。比如他在Codrops上分享的一个动动模糊的案例:
Gooey Effect 是SVG中使用filter
属性制作的最有吸引的效果,如下所示:
Lucas在CSS-Tricks上写了一篇文章,一步一步的告诉你如何创建这个效果,并且在Codrops还创建了一个根据音乐频率改变粘性的动画效果。
这些效果展示了SVG的能力,以及告诉我们如何做出更有趣的UI交互效果。我强列建议您看看Lucas在Codepen上写的有关于SVG的案例,你会受益良多。
总结
我们绝对没有涵盖所有内容,本文只是讨论了一些入门级别的概念,但我希望这个系列能让你更清的知道如何使用SVG来解决和改善我们设计中常见的一些问题,或者为这些设计提个一个更合理的,更适当的解决方案。
有的时候,有些设计方案使用SVG能做得比CSS更好,这也不可争的事实。然而,并没有说过SVG将替代CSS。应该说SVG和CSS是一个强大的组合,这个组合能让我们把静态的UI提高一个层次,进入一个全新的水平。