当我们在网站上创建新组件时,实际上是在创建不同大小的矩形,无论我们是否意识到这一点。 但是,如果我们想尝试一下呢? 制作形状有多少种不同的方法呢?
在这篇文章中,我想大致概述一些最常见的制作圆形、三角形和多边形的方法,并记下这些方法的优缺点,以便我们可以尝试那些我们可能不太熟悉的方法。
以下是一些在网络上制作形状的方法
border-radius
border
- 使用
transform
旋转形状 伪元素
box-shadow
- 使用
shape-outside
将文本包裹成形状 - 元素上的
clip-path
- SVG 资产
canvas
border-radius
例如,border-radius
属性可能是制作圆形的最简单方法
.element {
height: 500px;
width: 500px;
border-radius: 50%;
}
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 LVembR。
您可以为 border-radius
使用任何 长度值。 此外,如果您有兴趣,Jessica Eldredge 描述了 为什么我们应该使用 50% 而不是 100%,如果我们使用单个值同时设置所有四个角。
当然,我们也可以使用此属性制作许多其他形状,例如圆角矩形和椭圆形
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 5dd5c582ec9b79c7d8ac38c350bd3f02。
优点
- 得到现代浏览器的良好支持。
- 只需要少量 CSS 代码。
在年鉴中阅读有关 border-radius
属性的更多信息。
border
制作形状
使用 我们可以使用 border
属性制作许多不同的形状。 例如,通过将元素的三个边框的背景设置为 transparent
,我们可以模拟三角形的形状
.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;
}
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 vOpjXZ。
我们可以制作几乎朝任何方向指向的三角形。 这是一个解释其工作原理的动画教程
查看 CodePen 上由 Chris Coyier (@chriscoyier) 创建的 Animation to Explain CSS Triangles。
如果您想自动化此过程,可以使用 CSS Triangle Generator 来帮助您。 如果您需要一种更具程序性的方法来在代码库中生成 CSS 三角形,我们之前曾写过一篇关于 CSS Triangle Mixin 的文章。
使用这种技术也可以制作梯形
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 580955e70863188e57c68338d9dfa2ae。
优点
- 良好的浏览器支持。
- 有可用的工具,例如 CSS Shapes Generator,可以帮助轻松制作这些形状。
transform
旋转形状
使用 为了在 CSS 中制作某些形状,例如菱形,我们可以对普通的正方形使用 transform
属性
.diamond {
transform: rotate(45deg);
}
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 a4a12f6351b38e1a41e78676f20f0cf8。
在上面的示例中,由于变换,菱形被推出了其父元素。 我们需要在这里做的是使用 transform-origin
属性重新对齐菱形
.diamond {
transform: rotate(45deg);
transform-origin: 0 100%;
}
优点
- 良好的浏览器支持。
缺点
- 需要使用
transform-origin
修正形状的对齐方式,这在某些情况下可能很烦人。
伪元素
伪元素是使用纯 CSS 制作形状的非常重要的工具,因为它们极大地提高了您可以制作的形状数量。 例如,让我们以五边形为例
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 ca0b36c2d7ea75ea7fd5cd982c328006。
通过使用 :before
伪元素,我们可以制作两个不同的形状,然后将它们相互叠加。 但是,您可能会注意到该示例中 CSS 的一个问题是,将这两个部分绝对定位在一起的精确值非常麻烦。
这是我对使用 CSS 制作复杂形状的最大抱怨:所需的代码极其复杂。 一旦您走出五边形和六边形的范围,您就会发现需要一些非常复杂的代码,在大多数项目中,这可能被认为过于脆弱。
优点
- 您可以使用伪元素制作几乎任何形状。
- 不需要图像可能需要的额外 HTTP 请求。
缺点
- 在大型项目中,制作某些形状所需的代码可能会变得难以维护,并且从长远来看过于复杂而无法保留。
box-shadow
这可能是使用 CSS 制作形状最奇怪的方法,因为使用 box-shadow
属性可以创建令人难以置信的像素艺术渲染。 Samuel Marchal 的这个演示利用了这种技术。
优点
- 哇,你可以用
box-shadow
制作形状吗?
缺点
- 如果图像将来需要更改,这可能很烦人,因为编辑它需要找到该像素值在
box-shadow
属性中的确切位置。 - 图像无法通过 Illustrator、Photoshop 或 Sketch 等应用程序编辑。
shape-outside
将文本包裹成形状
使用 文本可以使用 shape-outside
属性围绕圆形、椭圆形或多边形等形状重新排列。 重要的是要注意,此属性目前仅对浮动元素有效,尽管这将来可能会改变。 这是一个简单的示例
.element {
float: left;
shape-outside: circle(50%);
width: 200px;
height: 200px;
}

有很多函数可以制作文本流动的形状,例如:circle()
、ellipse()
、polygon()
和 inset()
。 现在让我们仔细看看 ellipse()
函数
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 7fa99015d63597648d5e312c5b73ac25。
.element {
shape-outside: ellipse(150px 300px at 50% 50%);
}
ellipse()
函数需要椭圆 x 轴和 y 轴的半径值,然后是将形状中心定位在其边界框内的坐标。 例如,上面的示例会将椭圆的中心定位在 .element
的垂直和水平中心。
但是,这里有一个重要的注意事项,我们需要识别出来:当我们使用 shape-outside
时,我们并没有影响 .element
在这种情况下 的形状。 我们正在做的是改变它周围其他元素的关系。 如果我们在该 div 上添加边框和背景,我们会发现它仍然被渲染为矩形
查看 CodePen 上由 CSS-Tricks (@css-tricks) 创建的 5e47a80626dfa27a42dd18a0e2b8450b。
可以这样理解:使用 shape-outside
属性,我们改变的是元素周围其他元素的关系,而不是元素本身的几何形状。 要解决这个问题,我们需要将 shape-outside
与 clip-path()
属性一起使用,例如在这个示例中
查看 CSS-Tricks 在 CodePen 上的 4e5420d8c1a2766b25dd3c98f684bf9c。
shape-outside
属性还有很多内容,所以最好查看一下 Almanac 条目。
优点
- 允许文本的动态重排,这对于响应式界面来说可能很重要。
- 可以将边界框设置为边距、填充和边框。这让我们可以很好地控制这些关系的位置。
缺点
- 不受 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%);
}
查看 CSS-Tricks 在 CodePen 上的 84ce4f54c0d96b1ba0a2e9a9290876fb。
用逗号分隔的列表定义了形状中每个点的坐标,因此前两个值 0 100%
在 div
的左下角添加了一个点。接下来,我们在形状的右下角添加一个点,并在元素的左上角添加最后一个点。虽然这只是一个简单的三角形,但这个示例展示了开发人员可以用这个新属性对形状进行操作的能力。
此外,值得注意的是,clip-path
属性是完全可动画的,只要您将相同数量的条件传递到函数中。
查看 CSS-Tricks 在 CodePen 上的 10c03204463e92a72a6756678e6348d1。
如果这些函数看起来有点混乱,最好尝试使用 Clippy 等工具来帮助您弄清楚语法。

有关更多信息,请查看 clip-path
的 Almanac 条目 和 CSS 中的剪裁和遮罩。
优点
- 我们可以创建复杂的形状,而不需要请求另一个资产,比如图像。
缺点
- 如果您希望文本围绕形状环绕,则需要将
clip-path
与shape-outside
属性结合使用。
SVG
您可以用 **可缩放矢量图形** 绘制任何您想要的图形,从 游戏机 和徽标到图标系统和社交媒体按钮。
关于 如何使用 SVG 的详细介绍超出了本文的范围,因为有很多最佳实践和技巧需要提及。但一般来说,如果项目需要某种形状,我的默认选择是使用 SVG,因为这意味着更少的古怪、不可预测的代码,而这些代码对于更复杂的形状是必不可少的。这也意味着,如果设计人员需要进行修饰,他们可以轻松地编辑形状。
如果您想了解更多关于 SVG 的信息,请查看我们的 SVG 信息汇编。
优点
- 小文件大小(如果您对其进行了优化)。
- 您可以在任何流行的图形编辑器中绘制它们。
- 不熟悉 CSS 或 JavaScript 的人可以很容易地创建它们。
- 它们可以扩展到几乎任何尺寸而不会模糊。
- 广泛的浏览器支持和大量的可用回退。
- 您可以将它们添加到标记中,并 使它们对屏幕阅读器可访问。
- 可以使用 CSS 和 JS 进行动画处理。
缺点
- 如果它们是简单的形状,那么您可能可以使用纯 CSS 方法来代替。
canvas
canvas
元素对于图表或制作交互式游戏特别有用,因为它最初是为了用 JavaScript 绘制图形而设计的。不幸的是,关于 canvas
的教程超出了本文的范围,但了解它可以用于什么很有用。以下是我们如何用 canvas
绘制正方形。
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0074d9';
ctx.fillRect(0, 0, 100, 100);
查看 CSS-Tricks 在 CodePen 上的 194842e7086d6b740ba102fd3be9c510。
对于每个 canvas
,我们需要将 "2d"
字符串传递到 .getContext()
函数中。目前还没有 3d 上下文,但将来可能会实现。
MDN 有一个 很棒的 canvas
教程,如果您有兴趣了解如何用 JavaScript 操作形状,可以探索一下。
优点
- 非常适合制作游戏和交互式图表。
缺点
- 需要 JavaScript 作为依赖项。
总结
在网页设计中创建形状就像选择最佳的垂直对齐技术一样:没有完美的技术,一切都取决于您的需求。因此,在我最近参与的许多项目中,我没有选择一种技术,而是采用了几乎所有技术的组合。只要一切都已记录在案,并且您没有试图混淆其他开发人员,这些技巧就可以相互补充,解决在处理形状时遇到的任何问题。
Chris,很棒的文章。用 box-shadow 实现的这个技巧真的很酷。
这不是 Chris。Chris 招了一些新的作者。
我同意用 CSS 创建形状太难了。但是,随着 SVG 成为规范,这应该不再是一个问题。不过,了解 CSS 中的形状工作原理仍然非常有用。感谢这篇文章!
很棒的资源!感谢 Robin。
这就是 WebGL 的本质:Canvas 的 3D 上下文,通过
.getContext("webgl")
访问。您可以使用堆叠的背景渐变做很多事情。我创建了这个 mixin 来模拟我们还没有的角部形状。
http://codepen.io/ryandunn/pen/rVYPXr
例如,斜角很容易用于八边形,而挖空很容易用于四点圆形星形形状。
这是创建形状的最佳方法,感谢您介绍这个网站。
不错的资源网站
不错的文章。就像目前前端开发中的很多东西一样,没有绝对正确的形状创建方法。不过,SVG 似乎仍然是最广泛支持且最灵活的方法。也就是说,对于简单的形状来说,它显然有点过头了。
对于
shape-outside
,将“不改变元素的实际形状”列为缺点是错误的。正如其名称所暗示的那样,该属性本身并非旨在实现这一点。它真正改变的是(浮动)元素的浮动区域形状,这会影响布局,而不是图形。@Matthewe3man 我认为形状创建存在“正确选择”。如果是图形性质,则 SVG 是正确的解决方案。CSS 本身非常宽松,因此我们可以弯曲
box-shadow
、转换和其他属性来创造形状的错觉。但这通常会产生复杂的代码,这些代码脆弱且难以维护和调试。SVG 可以作为图像嵌入或引用。在经过深思熟虑的情况下,发出额外的 HTTP 请求来获取图像比在盲目追求性能的情况下混合复杂 CSS 代码更可取。
使用
shape-outside
属性时,应该与它一起添加pointer-events:none
,这样用户就可以再次选择剪裁的文本,即使单击了元素。