谈谈如何利用 CSS 的 border 属性绘制三角形

绘制三角形

如图所示, 我们构造一个宽高都为 50pxdiv 元素(图中的白色盒子),并将边框宽度 设置为:上边框 80px、下边框 40px、左边框100px、右边框 50px

代码如下

html 复制代码
<div id="box">
   <span>50px</span>
</div>

<style>
 #box {
      width: 50px;
      height: 50px;
      line-height: 50px;
      text-align: center;
      border-top: 80px solid rgb(248, 180, 180);
      border-bottom: 40px solid rgb(155, 155, 255);
      border-left: 100px solid rgb(169, 255, 169);
      border-right: 50px solid yellow;
   }
</style>

这时,我们得到 4 个梯形 ,那么,怎么获得三角形 呢? 如果运用极限的思想三角形 可以看成是梯形一条边长度为 0 的结果。因此,我们尝试将 div 元素的宽高都设置为 0 ,即 width: 0height: 0

html 复制代码
<div id="box"></div>

<style>
 #box {
      width: 0;
      height: 0;
      line-height: 50px;
      text-align: center;
      border-top: 80px solid rgb(248, 180, 180);
      border-bottom: 40px solid rgb(155, 155, 255);
      border-left: 100px solid rgb(169, 255, 169);
      border-right: 50px solid yellow;
   }
</style>

我们成功获得了 4 个三角形:

那么,如何获得一个单独的三角形,比如左边这个绿色的三角形呢?这时候,我们就需要通过 transparent 这个 CSS 值将边框颜色设置为透明 ( transparent 的意思是 透明的 ):

html 复制代码
<div id="box"></div>

<style>
 #box {
      width: 0;
      height: 0;
      line-height: 50px;
      text-align: center;
      border-top: 80px solid tranparent;
      border-bottom: 40px solid transparent;
      border-left: 100px solid rgb(169, 255, 169);
      border-right: 50px solid transparent;
   }
</style>

成功了!

绘制直角三角形

但是,当我们想获得任意形状的三角形时,上面的思路显然不够简洁。怎么办呢?首先,让我们换个思路来看看这个绿色三角形的产生过程。

因为任意一个三角形都可以过顶点作对边的垂线,所以任意一个三角形都可以由两个直角三角形拼接而成。我们的问题便转化为了如何绘制任意直角三角形

让我们继续从上面的绿色三角形入手。左边三角形的 100px80px40px 分别来自左边框、上边框和下边框。我们如何从这个三角形出发,获得右上角的三角形呢?是的,我们可以再次运用极限 的思想,右上角的三角形相当于将下边框 的宽度设置为 0 : border-bottom: 0px solid transparent;

html 复制代码
<div id="box"></div>

<style>
 #box {
      width: 0;
      height: 0;
      border-top: 80px solid transparent;
      border-bottom: 0px solid transparent;
      border-left: 100px solid rgb(169, 255, 169);
      border-right: 50px solid transparent;
   }
</style>

更进一步,我们可以直接删除border-bottom 属性的声明:

html 复制代码
<div id="box"></div>

<style>
 #box {
      width: 0;
      height: 0;
      border-top: 80px solid transparent;
      border-left: 100px solid rgb(169, 255, 169);
      border-right: 50px solid transparent;
   }
</style>

当我们仔细观察代码的时候,可以发现右边框的 50px 并没有在图片中体现出来,让我们再试试删除 border-right 属性:

html 复制代码
<div id="box"></div>

<style>
 #box {
      width: 0;
      height: 0;
      border-top: 80px solid transparent;
      border-left: 100px solid rgb(169, 255, 169);
   }
</style>

依然可以。现在,让我们从代码反推回去,找找套路。假设我们想画一个直角三角形,我们可以从它的任意一个锐角顶点 出发,用一笔画的方法画出三角形。比如:

第一笔 ,向 画,对应左边框 被设置为有颜色border-left: 100px solid rgb(169, 255, 169);第二笔 ,向 画,对应上边框 颜色被设置为透明border-top: 80px solid transparent;

我们得出以下规律:

  1. 锐角顶点作为上下左右方向的参考点
  2. 往哪个方向画,就设置哪个方向的边框
  3. 第一笔对应的边框设置为有颜色;第二笔对应的边框颜色设置为透明

现在,我们可以随意画出一个三角形了:

html 复制代码
<div id="triangle"></div>
</div>

<style>
    #triangle {
        width: 0;
        height: 0;
        border-bottom: 80px solid greenyellow;
        border-left: 200px solid transparent;
        border-right: 20px solid transparent;
    }
</style>

旋转三角形

我们能够随心所欲地画出四平八稳 的三角形了。那么,如何画出斜着的三角形呢?这时候,transform: rotate() 就派上了用场。当然,除了 transform,我们还需要 transform-origin 来确定旋转中心。如下图,我们想将绿色三角形旋转至红色三角形的位置,首先,我们取绿色三角形斜边的中心点作为参考点 (图中的黑色圆点),我们的旋转中心位于此参考点的右上方 ,因此,我们要设置 transform-origin: top right。同时,旋转角度为正时,图形按顺时针方向旋转 ,对于下图,我们设置的是transform: rotate(10deg)

于是,我们可以写出以下代码:

html 复制代码
<div id="rotate"></div>
</div>

<style>
    #rotate {
        width: 0;
        height: 0;
        border-bottom: 80px solid greenyellow;
        border-left: 200px solid transparent;
        transform: rotate(10deg);
        transform-origin: top right;
    }
</style>

结果如下

对于直角三角形,我们可以从三个顶点中任选一个作为旋转中心,但如果是非直角三角形 ,为了方便和确定性,旋转中心最好选取位于底边上的两个顶点。比如:

利用 transform-origin: bottom right 选择右下方的顶点作为旋转中心:

显然要比利用 transform-origin: top right 选择右上方的顶点作为旋转中心:

容易控制得多。

实际上,我们的旋转中心仍然是正方形/长方形盒子的顶点,只是有些顶点刚好跟三角形顶点重合了:

最终代码

html 复制代码
<div id="triangle"></div>
</div>

<style>
    #triangle {
        width: 0;
        height: 0;
        border-bottom: 80px solid greenyellow;
        border-left: 200px solid transparent;
        border-right: 20px solid transparent;
        transform: rotate(10deg);
        transform-origin: bottom right;
    }
</style>

大功告成!

参考资料

border-width (MDN)

transform (MDN)

rotate() (MDN)

transform-origin (MDN)

相关推荐
bobz9658 小时前
进程和线程结构体的统一和差异
面试
Java中文社群13 小时前
重要:Java25正式发布(长期支持版)!
java·后端·面试
沐怡旸14 小时前
【底层机制】std::string 解决的痛点?是什么?怎么实现的?怎么正确用?
c++·面试
bobz96515 小时前
QoS 中的优先级相关的设计
面试
就是帅我不改15 小时前
揭秘Netty高性能HTTP客户端:NIO编程的艺术与实践
后端·面试·github
isysc117 小时前
面了一个校招生,竟然说我是老古董
java·后端·面试
uhakadotcom17 小时前
静态代码检测技术入门:Python 的 Tree-sitter 技术详解与示例教程
后端·面试·github
bobz96519 小时前
进程面向资源分配,线程面向 cpu 调度
面试
绝无仅有19 小时前
数据库MySQL 面试之死锁与排查经验总结
后端·面试·github
Lotzinfly20 小时前
12个TypeScript奇淫技巧你需要掌握😏😏😏
前端·javascript·面试