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;
/* 其他三个透明,只保留红色三角形 */
}
关键原理
- 边框斜接:当相邻边框颜色不同时,交接处会形成对角线
- 宽高为 0:使得 content 区域消失,边框变成四个三角形
- 透明边框:将不需要的边设为 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>
面试要点
- 能够画出三角形的 CSS 代码
- 能够解释 border 形成三角形的原理
- 知道如何实现带边框的三角形
- 了解 clip-path 等现代替代方案
- 能够举一反三,画出梯形、气泡框等复杂形状
原理总结:
- 边框相交处形成对角线
- 宽高为 0 时边框变成三角形
- 将不需要的边设为 transparent