在 Web 开发中生成几何图形的几种方式
原文链接 https://bubkoo.github.io/2015/07/22/working-with-shapes-in-web-design/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
当我们在进行 Web 开发时,很多时候都是在有意或无意地创建一些矩形,深究一下,到底有多少中方式来得到一个几何图形呢?本文将简单介绍几种生成圆形、三角形和多边形的方式,并分析每种方式的优缺点。
下面是可能使用到的方式:
- border-radius
- border
- rotating shapes with transform
- pseudo elements
- box-shadow
- wrapping text into shapes with shape-outside
- clip-path on an element
- SVG assets
- canvas
<!--more-->
border-radius
使用 border-radius
样式属性是得到圆形的最简单的方式:
.element {
height: 500px;
width: 500px;
border-radius: 50%;
}
border-radius
的属性值可以是长度值或百分比。值为 50%
和 100%
时都可以得到一个圆形,Jessica Eldredge 有篇文章介绍了为什么要使用 50% 而不是 100%。
使用该属性还可以制作出其他形状,如圆角矩形,椭圆形等。
优点:
- 支持现代浏览器;
- 只需要少量的 CSS。
border
通过设置 CSS 中的 border
属性我们可以一些不同的图形,例如,通过将一个元素的三个边框颜色设置为透明,我们可以模拟一个三角形的样子:
.triangle {
height: 0;
width: 0;
border-left: 100px solid red;
border-right: 100px solid transparent;
border-bottom: 100px solid transparent;
border-top: 100px solid transparent;
}
我们可以使三角形指向任何想要的方向,下面是一个动画教程:
你可以使用 CSS 三角形生成器来帮你自动生成一个三角形,如果你想以编程的方式来实现一个三角形,这里有一个 CSS 的 Mixin。
也可以是使用该技术来得到一个梯形:
优点:
- 浏览器都支持;
- 有现成的工具可用,比如,CSS 形状生成器,可以很方便地生成你想要的几何形状。
transform
可以使用 transform
来做出特定的形状,如钻石形状:
.diamond {
transform: rotate(45deg);
}
在上面例子中,由于 transform
旋转,导致图形溢出了父元素,我们可以通过 transform-origin
来调整:
.diamond {
transform: rotate(45deg);
transform-origin: 0 100%;
}
优点:
- 支持现在浏览器。
缺点:
- 需要使用
transform-origin
来修正元素的位置,这可能会不好调整。
Pseudo elements
Pseudo elements(伪元素)是利用 CSS 制作几何形状的重要工具,大大提高了可制作形状的数量,如下面的五角形:
使用 :before
为元素,我们生成了两个不同的形状,其中一个在另一个的上面,通过上例中的 CSS 可知,为了得到这个形状,对两个形状的位置要求非常严格。这是我对使用 CSS 来制作复杂形状最不满意的地方:越复杂的形状要求越复杂的代码,一旦你得到五边形或六边形后,你会发现这样的代码非常丑陋,在项目中这样的的代码是不可维护的。
优点:
- 可以制作任何你想要的形状;
- 不用像图片一样需要额外的 HTTP 请求。
缺点:
- 在大型项目中,制作复杂形状的代码会变得不可维护,也不是长久之计。
box-shadow
这也许是使用 CSS 制作形状最奇怪的方式,因为使用 box-shadow
可以创造惊人的艺术效果。看下面的 demo:
优点:
- 你可以使用
box-shadow
制作形状?
缺点:
- 如果将来想修改图形,需要精确找到像素位置对应的
box-shadow
属性,这是个烦人的工作; - 得到的形状不可以被第三方软件编辑,比如 Illustrator,Photoshop 或 Sketch。
使用 shape-outside 使文字围绕图形
使用 shape-outside
属性可以使文字围绕图形(圆、椭圆或多边形)。需要注意的是:目前这个属性只对浮动元素有效。看下面这个简单的例子:
.element {
float: left;
shape-outside: circle(50%);
width: 200px;
height: 200px;
}
shape-outside
属性对应的方法有:circle()
, ellipse()
、polygon()
和 inset()
,下面这个例子使用了 ellipse()
方法:
.element {
shape-outside: ellipse(150px 300px at 50% 50%);
}
使用 ellipse()
方法时需要指定椭圆需要的 x 和 y 半径,其次是椭圆的中心位置。在上例中,椭圆的中心位置就位于元素的中心位置上。
然后,这里有一个需要注意的问题:当使用 shape-outside
属性时,并不会影响元素本身的形状,只影响了围绕它的其他元素的形状。如果为该元素这是一个边框和背景,我们将发现该元素仍然是一个矩形:
你可以这样来理解:使用了 shape-outside
属性的元素只改变了围绕它的其他元素,而元素本身的几何形状并没有改变。为了改变元素自身的形状可以将 shape-outside
和 clip-path()
结合使用,例如:
还有很多没有涉及到的内容,如果想要深入了解 shape-outside
属性,可以参考这篇文章。
优点:
- 可以实现文字环绕形状效果;
- 可以设置形状的
margin
、padding
和border
属性,这可以使我们对元素位置进行精细控制。
缺点:
- IE 和 Firefox 不支持该属性;
- 不改变元素的实际形状。
clip-path
与上面介绍的 shape-outside
属性一样,clip-path
属性可以使用的方法有:inset()
、polygon()
和 ellipse()
,看下面这个例子:
.element {
width: 200px;
height: 200px;
clip-path: polygon(0% 100%, 100% 100%, 0% 0%);
}
clip-path
属性是完全支持 CSS3 动画的:
可以使用 Clippy 这样的工具来生成你需要的代码:
深入阅读可以参考:
优点:
- 可以制作复杂的形状,而不需要图片这样的额外资源。
缺点:
- 实现文字环绕图片效果需要结合使用
clip-path
和shape-outside
这两个属性。
SVG
使用 SVG(可缩放的矢量图形)可以制作出任何你想要的图形,如 console、logo、图标、社会媒体按钮等。
本文并不会教你如何使用 SVG,因为涉及太多的最佳实践和技术细节。通常,如果一个项目需要使用到图形,我的首选肯定是 SVG,因为这意味着更少的奇怪的不可预知的代码,也意味着如果设计师需要对图形进行润色,他们可以随时编辑这些形状。
如果想详细了解 SVG,这里有一篇关于 SVG 的汇总文章。
优点:
- 较小的文件大小;
- 可以在任何流行的图形编辑器中编辑它们;
- 不熟悉 CSS 和 JavaScript 的人也可以制作它们;
- 无失真缩放;
- 广泛的浏览器支持和大量的兼容方案;
- 可以将它们添加到页面标签中,并可以支持屏幕阅读器;
- 支持 CSS 和 JavaScript 动画。
缺点:
- 如果它们是非常简单的形状,你可以使用纯 CSS 的方案来实现。
canvas
使用 canvas
元素来制作图表和互动式游戏非常有用,因为它的设计初衷就是用来绘制图表。canvas
绘图教程超出了本文的范围,这里你需要了解的是用 canvas
可以做什么,下面是使用 canvas
来绘制一个正方形:
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0074d9';
ctx.fillRect(0, 0, 100, 100);
对每个 canvas
,我们需要给 .getContext()
方法传递 "2d"
这个字符串参数,目前还没有 3d 上下文,也许将来会支持。
在 MDN 上有一系列关于 canvas 的教程。
优点:
- 制作游戏和交互式图表。
缺点:
- 依赖 JavaScript。
总结
选择一种制作图形的方式,就与选择一种垂直对齐方式一样:没有最好的方案,只有最适合项目的方案。在我的项目开发中,我并没有只选择其中一种技术,而是将这些方式使用在最适合它们的位置,同时注意保持完善的文档,并且不给其他开发人员造成困扰。
参考资源
- Almanac entry for clip-path
- More info about clip-path
- W3C on CSS Shapes
- The Shapes of CSS
- Getting started with CSS Shapes
- Clippy
- Adobe’s CSS Shapes CodePen collection
- Clipping and masking in CSS
- Border-radius: 50% vs 100%
- How to get started with CSS shapes
- Shapes editor Chrome extension
- Canvas tutorial on MDN
- A compendium of SVG information