前端知库

怎样用 CSS 画一个三角形?原理是什么?

把元素宽高设为 0,只给边框设宽度,四条边框在角上按斜线拼接,每条边各自变成一个三角形。把不需要的三条边设为透明,就剩下一个三角形。现在也可以用 clip-path: polygon() 直接裁剪出三角形,写法更直观,还能用背景色和渐变。

参考答案

简答

下拉菜单旁边的小箭头、气泡提示框的尖角,都是三角形。最经典的画法是利用边框:把元素的宽高都设成 0,再给四条边框分别设宽度和颜色。

原理在于边框在角上是按斜线拼接的。一个元素四条边框都很粗、颜色各不相同时,你能看到每条边框是一个梯形,相邻两条在角上沿对角线相接。宽高缩到 0 以后,中间的内容区没了,每个梯形的短边缩成一个点,四条边框就变成了四个三角形,尖角都朝向中心。

只想要一个朝下的三角形,就只保留上边框的颜色,把左右边框设成透明,下边框不设。三角形的高度由上边框的宽度决定,底边宽度是左右边框宽度之和。

另一种写法是 clip-path: polygon(50% 0, 100% 100%, 0 100%),给一个正常大小的元素裁剪出三角形。它更直观,元素有真实的宽高,背景可以用渐变或图片。要注意,边框法画出来的是透明边框加有色边框,透明部分仍然占着位置。

边框法

CSS
.arrow-down {
  width: 0;
  height: 0;
  border-top: 10px solid #333;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
}

这样得到一个底边 16px、高 10px、尖角朝下的三角形。

为什么不需要写 border-bottom?如果写了透明的下边框,元素在下方还会多占一段透明的高度,箭头和后面的内容之间就多出空白。只写上、左、右三条边,元素的总高度就正好是上边框的 10px,总宽度是左右边框之和 16px。在 Chrome 里测量,这个元素的尺寸确实是 16×10。

为什么左右边框必须是透明的,而不是不写?上边框是梯形,它的两条斜边是靠左右边框“切”出来的。如果没有左右边框,上边框就是一个普通的矩形,画出来是一条 10px 高的横线。

想要别的方向,就换一条有颜色的边框:尖角朝上用 border-bottom 加透明的左右边框,朝左用 border-right 加透明的上下边框。

clip-path 写法

CSS
.arrow-clip {
  width: 16px;
  height: 10px;
  background: linear-gradient(#333, #999);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

polygon 里每对数字是一个顶点坐标,百分比相对元素自身的宽高。这里三个点是左上角、右上角和底边中点,连起来就是一个朝下的三角形。元素本身是正常的 16×10 盒子,背景可以用渐变,这是边框法做不到的。

clip-path 裁掉的部分看不见,也不响应点击,但元素在布局里仍然占着完整的矩形。

常见追问

气泡提示框的尖角怎么做?

给气泡加一个 ::after 伪元素,用边框法画三角形,position: absolute 定位到气泡边缘。需要尖角带边框时,再叠一个稍大一点、颜色是边框色的三角形在下面,露出的一圈就是边框。

画一个扇形或者圆怎么写?

圆用 border-radius: 50%。扇形可以用 conic-gradient 画出一块颜色,再配合 border-radius: 50% 裁成圆形,比用边框拼方便得多。