一、前言
看到这个标题,确实容易让人产生疑惑,我的 CSS 这么 6,有了它,感觉我已经无所不能了,为啥要用把它替代掉?
下面,我们将从自身定位、开发体验、维护成本、兼容性等各个方面,简单分析一下。
二、自身定位
- CSS ,Cascading Style Sheets,中文名叫层叠样式表,从它自身名字以及广泛的使用方式来看,它的功能,主要集中在格式化 HTML 样式,主要包括字体、排版等方面的内容;
- SVG ,Scalable Vector Graphics,中文名可缩放矢量图形,名字中的图形二字,就不难看出,它主要注重解决图形处理方面的问题。
从一定程度上来讲,图形处理方面,CSS 就像一个业余选手,而 SVG 则是我们的专业运动员。
三、开发体验
闭着眼睛跟我谈什么开发体验?直接上代码先!Talk is cheap! Show me the code!
下面我们就结合几个常见的应用场景来体验一下 CSS 也 SVG 在开发上的不同体验:
(一)画一条斜线
这可能是最简单、但又最直观的例子了。
1. CSS version
<style>
.line {
width: 100px;
border-bottom: 1px solid black;
transform: rotate(45deg);
}
</style>
<div class="line"></div>
2. SVG version
<svg>
<line x1="0" y1="0" x2="100" y2="100" stroke="black" stroke-width="1"/>
</svg>
二者的实现效果大致如下图:
我想,聪明的你应该已经发现问题了吧,两条线长度不一样,原理其实也很简单。CSS 版的,是通过将一根长度为 100px 的线,顺时针旋转了 45 度形成的,其长度为 100px;SVG 版的,是一根(0, 0)点到(100,100)点的连线,根据勾股定理,其长度应该是 100 * Math.sqrt(2),也就是 100 乘以根号2,所以会比前者长。于是,更多问题就出来了。。。
- 长度。常规的设计稿上,我们可以轻松拿到一条斜线首尾两点的位置用于 SVG 绘制,但是 CSS 依赖于它的长度。。。这样的话,只能说。。。勾三股四弦五。。。demo 中的线条,我们是一个顺时针旋转 45 度角的直线,可以认为是一个等腰直角三角形的斜边,要计算它的长度还比较方便,其它情况,计算起来就更麻烦了
- 角度。和上说的一样,我们可以轻松拿到设计稿上斜线首尾两点的位置,所以使用 SVG 绘制的时候,我们可以完全关心它的角度问题;使用 CSS 绘制的时候,你可能需要拿一个量角器到屏幕上的设计稿中量一下斜线的倾斜角度,哦,对了,记得添加一条水平的辅助线便于测量
- 位置。使用 SVG 绘制的斜线,画到哪儿就在哪儿;使用 CSS 绘制的斜线,默认会有一个 transform-origin 控制它旋转的时候以哪个点为中心,有时候,为了不让它跑偏,你可能需要手动控制一下。
(二)画一个朝上的三角形箭头
1. CSS version
<style>
.tri-angle {
width: 0;
height: 0;
border: 10px solid white;
border-bottom: 10px solid black;
}
</style>
<div class="tri-angle"></div>
2. SVG version
<svg>
<polygon points="10 0, 20 10, 0 10" style="fill:black;"/>
</svg>
二者的实现效果大致如下图:
问题分析:
- 大小。审查元素不难发现,使用 CSS 绘制的原本有效区域未 20 * 10 的箭头,结果却需要 20 * 20 的区域,顶上存在了 20 * 10 的无效区域。同样的方式绘制朝右的箭头,右侧也会存在相应大小的无效区域
- 位置和布局。由于上面提到的无效区域的存在,在管理图标位置和页面布局的时候,往往容易出现一些问题
- 形状。这里是绘制的等腰直角三角形,通过改变两侧 border 的宽度,我们还可以绘制出一般的等腰三角形。但如果要绘制三条边不一样长的三角形呢?SVG 实现依旧没有任何困难,而 CSS。。。可能需要经过繁杂的计算了。
依照类似的方式,CSS 还可以利用各种奇怪的方式,绘制出五边形、六边形、五角星等各种典型的图形,但是,其复杂程度,随图形的复杂程度不停的上升,在处理不规则图形的时候,特为尤甚。
啥?你说像五角星之类的,顶点数量太多,也很难取?不好意思,在 PS 的图层的右键菜单上,有一个复制 SVG 选项,你要不试一试?
P.S. 相邻位置上,还有一个复制 CSS 选项,一般情况下,除了复制阴影效果等,建议还是不要尝试了。
四、维护成本
1. 需求变更
产品和开发天生是一对冤家。我们没有办法保证需求不会变更,也不可能真让产品“扫码改需求”,那么作为开发我们真的就只能认命?也不全是,我们可以通过调整自己的开发模式,让需求变更的时候,做出相应修改时的时间、人力成本降低,进而降低项目的维护成本。比如一开始的那条斜线,这次我们需要让右下角的点不动,左上角的点向下移动 3 个像素,你可以用 CSS 、SVG 都试试怎么实现。
2. 普适性
还是拿最开始的斜线来说事。CSS 和 SVG 其实代表了两种不同的处理方式,CSS ——极坐标系,SVG 是笛卡尔(直角)坐标系。
大多数情况下,我们拿到的设计稿,一般都是基于笛卡尔坐标系的,只有少数专业性非常强的领域(如数学、物理等)才会必须使用类似极坐标系等方式,但这时候,大都会使用更加专业化的手法,而非 CSS。事实上,SVG 也能很好的处理极坐标系的图形,有兴趣可以学一下。所以,在图形绘制上,SVG 有着 CSS 难以企及的普适性。
3. 开源项目
事实证明,相比于用 CSS 中各种奇怪的手法,SVG 将更容易与我们的项目相结合,当然,这里说的是图形绘制。现在,CSS 已经有了很多相对成熟的“框架”,最典型的,莫过于 Bootstrap。但是纵观其功能,更多的是页面布局、风格样式相关的功能,框架内部的图形,基本都是依赖于其引用的 webfont,而没有通过 CSS 去 hack。反观 SVG,要不你去看一下这个项目 传送门。CSS 擅长的,本来就应该是各种布局、样式等效果,有时间可以去看一看这个项目传送门。个人精力有限,我这里列举的可能比较狭隘,大家有兴趣可以更多地去关注一下。
4.副作用
使用 CSS hack,往往会带来很多的副作用:一开始的斜线,使用 CSS 的时候,你去看过它所占的位置么?三角形箭头的实现,也必须占据更多的位置;CSS3 中的变形、旋转等,都可能会使得元素展示的位置与它实际在文档流中占据的位置不符,这使得我们在维护这样的代码的时候,经常需要额外的时间和精力。
五、兼容性
下面是 caniuse.com 中查询到的兼容性信息:
不难看出,比较主流的浏览器基本都已经实现了对 SVG 的支持,只有 IE8 例外,但实际上,它也可以通过安装插件的形式实现对 SVG 的支持。
综上,我们没有理由拒绝 SVG。