返回首页

CSS 如何画一个三角形?原理是什么?

问题解析

用 CSS 画三角形是一个经典的"奇技淫巧",考察的是对盒子模型,特别是 border 特性的深入理解。面试官希望看到候选人能够解释原理,而不仅仅是背代码。

实现方法

基础三角形

.triangle {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 50px;
  border-color: transparent transparent transparent red;
  /* 指向右边 */
}

不同方向的三角形

/* 上 */
.triangle-up {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 50px solid red;
}

/* 下 */
.triangle-down {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-top: 50px solid red;
}

/* 左 */
.triangle-left {
  width: 0;
  height: 0;
  border-top: 50px solid transparent;
  border-bottom: 50px solid transparent;
  border-right: 50px solid red;
}

/* 右 */
.triangle-right {
  width: 0;
  height: 0;
  border-top: 50px solid transparent;
  border-bottom: 50px solid transparent;
  border-left: 50px solid red;
}

直角三角形

/* 左上直角 */
.triangle-top-left {
  width: 0;
  height: 0;
  border-top: 50px solid red;
  border-right: 50px solid transparent;
}

/* 右上直角 */
.triangle-top-right {
  width: 0;
  height: 0;
  border-top: 50px solid red;
  border-left: 50px solid transparent;
}

原理详解

Border 的本质

CSS 的 border 并不是一条直线,而是四个梯形(或三角形)组成的。

当元素有宽高时:

┌─────────────────┐
│    上边框        │
│  ┌─────────┐    │
│左│ content │ 右 │
│  └─────────┘    │
│    下边框        │
└─────────────────┘

当宽高为 0 时:

    /\
   /  \      ← 上边框
  /____\
 /\    /\
/  \  /  \    ← 左右边框形成三角形
‾‾‾‾‾‾‾‾‾‾
   下边框

三角形形成过程

.step1 {
  width: 50px;
  height: 50px;
  border: 20px solid;
  border-color: red green blue yellow;
  /* 显示为四个彩色梯形 */
}

.step2 {
  width: 0;
  height: 0;
  border: 20px solid;
  border-color: red green blue yellow;
  /* 显示为四个三角形 */
}

.step3 {
  width: 0;
  height: 0;
  border: 20px solid;
  border-color: transparent transparent transparent red;
  /* 其他三个透明,只保留红色三角形 */
}

关键原理

  1. 边框斜接:当相邻边框颜色不同时,交接处会形成对角线
  2. 宽高为 0:使得 content 区域消失,边框变成四个三角形
  3. 透明边框:将不需要的边设为 transparent,露出需要的三角形

进阶应用

带边框的三角形

/* 外层三角形 */
.triangle-with-border {
  position: relative;
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 50px solid #333; /* 边框色 */
}

/* 内层三角形(小一号,覆盖在上面) */
.triangle-with-border::after {
  content: '';
  position: absolute;
  top: 2px;  /* 微调位置 */
  left: -46px; /* 宽度的一半减去边框 */
  width: 0;
  height: 0;
  border-left: 46px solid transparent;
  border-right: 46px solid transparent;
  border-bottom: 46px solid white; /* 背景色 */
}

气泡框

.bubble {
  position: relative;
  padding: 15px;
  background: #f0f0f0;
  border-radius: 8px;
}

/* 小三角 */
.bubble::before {
  content: '';
  position: absolute;
  top: -10px;
  left: 20px;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 10px solid #f0f0f0;
}

梯形

.trapezoid {
  width: 100px;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
}

平行四边形

.parallelogram {
  width: 150px;
  height: 100px;
  background: red;
  transform: skew(-20deg);
}

五角星

.star {
  position: relative;
  display: inline-block;
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 35px solid red;
  transform: rotate(35deg);
}

.star::before,
.star::after {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 35px solid red;
}

.star::before {
  transform: rotate(-70deg);
  left: -50px;
}

.star::after {
  transform: rotate(70deg);
  top: 3px;
  left: -52px;
}

现代替代方案

Clip-path(现代浏览器)

.triangle-clip {
  width: 100px;
  height: 100px;
  background: red;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

/* 更复杂的形状 */
.pentagon {
  clip-path: polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%);
}

SVG

<svg width="100" height="100">
  <polygon points="50,0 0,100 100,100" fill="red"/>
</svg>

最佳实践

/* 工具类 */
.triangle {
  display: inline-block;
  width: 0;
  height: 0;
  border-style: solid;
}

.triangle-up {
  border-width: 0 10px 10px 10px;
  border-color: transparent transparent currentColor transparent;
}

.triangle-down {
  border-width: 10px 10px 0 10px;
  border-color: currentColor transparent transparent transparent;
}

.triangle-left {
  border-width: 10px 10px 10px 0;
  border-color: transparent currentColor transparent transparent;
}

.triangle-right {
  border-width: 10px 0 10px 10px;
  border-color: transparent transparent transparent currentColor;
}
<!-- 使用 -->
<span class="triangle triangle-down" style="color: red;"></span>

面试要点

  1. 能够画出三角形的 CSS 代码
  2. 能够解释 border 形成三角形的原理
  3. 知道如何实现带边框的三角形
  4. 了解 clip-path 等现代替代方案
  5. 能够举一反三,画出梯形、气泡框等复杂形状

原理总结

  • 边框相交处形成对角线
  • 宽高为 0 时边框变成三角形
  • 将不需要的边设为 transparent