# CSS画一个三角形

三角形的场景很常见,打开一个页面可以看到各种各样的三角形。

​ 由于div一般是四边形,要画一个三角形并不是那么直观。你可以贴一张png,但是着各种办法有点low;也可以使用svg 的形式,但是太麻烦。三角形其实是可以用css来画的。css画三角形可以分为两种:一种是纯色的三角形,第二种是有边框色的三角形,三角形可以用border画出来,首先一个有四个border的div应该是这样的,如下图

所示

图片

代码如下

<style>
.triangle{
border-right: 50px solid #333;
border-left: 50px solid #000;
border-top: 50px solid #666;
border-bottom: 50px solid #999;
width: 100px;
height: 100px;
background-color: #ccc;
}
</style>
<div class="triangle"></div>

然后把他的宽度和高度都设置为0,剩下四个border,就变成如下所示了

图片

​ 再把border-top去掉,这样就把上面的区域给裁掉了,如下图所示

图片

接下来就是让左右两边的border透明,background的背景色去掉

就得到一个三角形,如下图所示

图片

代码清单如下

<style>
.triangle{
border-right: 50px solid transparent;
border-left: 50px solid transparent;
border-bottom: 50px solid #999;
width: 0px;
height: 0px;
}
</style>
<div class="triangle"></div>

这里是了底部的border作为三角形,如果要取左边的border,同理只需让上下的

两个border颜色设置为transparent,同时不要右边的border即可。

# 控制三角形的角度

​ 上面画的三角形是一个直角三角形,而用的比较多的应该是等边三角形或者接近于

等边三角形,那怎么画一个等边三角形呢?

​ 首先,保持border-left和border-right的大小不变,让border-bottom不断变大,

观察一下形态是怎么变的,如下所示

图片

​ 经过上图的解释,应该明白了角度是如何调整的,需要用到三角形的数学公式,

如果要制作等边三角形,那么应该 左右两边的边框一样宽度,底部边框的高度应为

左(右)边框的根号3倍;如40px的根号3倍约为 69.28px;如下图所示,就为等边

三角形

图片

# 画一个有边缘的三角形

​ 这种三角形很常见,特别是tip的提示框、聊天消息框等。

​ 这种画法的实现其实很简单,只是不容易想到——就是先画一个深色的三角形,然

后再画一个同样大小白色的三角形盖在上面,两个三角形错位两个像素,这样深色的边

缘就刚好露出一个像素。

代码清单如下

<style>
.chat-msg{
width: 300px;
height: 80px;
border: 1px solid #ccc;
position: relative;
border-radius: 10px;
}
.chat-msg:before{
content: '';
position: absolute;
left: -10px;
top: 34px;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 10px solid #ccc;
}
</style>
<div class="chat-msg"></div>

效果如下

图片

然后再画一个白色的三角形盖上去,错位两个像素,代码清单如下

.chat-msg:after{
content: '';
position: absolute;
left: -8px;
top: 34px;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 10px solid #fff;
}

效果如下

图片

​ 上面用的属性都是css2最基本的属性,所以没有兼容性问题

# 添加阴影

​ 如果三角形要有阴影怎么办?可以用filter添加阴影效果,如下代码所示

.chat-msg{
   filter: drop-shadow(0 0 2px #999);
   background: #fff;
}

效果如下

图片

# 项目实战

使用css画一个聊天气泡
娘子,啊哈
老公,什么车最贵?
你猜?
布加迪??
不对,你再猜
法拉利?
告诉你什么最贵,你们女人的购物车。
滚。。。

以上部分需要上下左右居中对齐,部分左对齐。需要根据内容来自适应高度,整块相对来说对CSS的要求还是比较高的。如有类似的可来这里参考。

<template>
  <div class="draw-triangle">
    <div class="title">使用css画一个聊天气泡</div>
    <div class="mobile-box">
      <div class="header-box">
        <div class="back">
          <i class="el-icon-arrow-left"></i>
        </div>
        <div class="header-title">娘子,啊哈</div>
      </div>

      <div class="content-box" ref="chatContent">
        <div :class="['chat-box', item.isSelf ? 'right' : '']" v-for="(item, index) in chatContentList" :key="index">
          <div :class="['avatar', item.isSelf ? 'right' : '']">
            <img class="avatar-img" :src="item.avatar" alt="">
          </div>
          <div :class="['chat-content', item.isSelf ? 'right' : '']">
            {{item.content}}
          </div>
        </div>
      </div>

      <div class="input-box">
        <el-input v-model="msg" @keyup.enter.native="sendMessage"></el-input>
        <div class="right">
          <i class="icon el-icon-circle-plus-outline"></i>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "draw-triangle",
  data() {
    return {
      msg: "",
      chatContentList: [
        {
          isSelf: false, //是否是自己发送的消息
          avatar: require("../../public/imgs/mz.jpg"),
          content: "老公,什么车最贵?"
        },
        {
          isSelf: true, //是否是自己发送的消息
          avatar: require("../../public/imgs/12.jpg"),
          content: "你猜?"
        },
        {
          isSelf: false, //是否是自己发送的消息
          avatar: require("../../public/imgs/mz.jpg"),
          content: "布加迪??"
        },
        {
          isSelf: true, //是否是自己发送的消息
          avatar: require("../../public/imgs/12.jpg"),
          content: "不对,你再猜"
        },
        {
          isSelf: false, //是否是自己发送的消息
          avatar: require("../../public/imgs/mz.jpg"),
          content: "法拉利?"
        },
        {
          isSelf: true, //是否是自己发送的消息
          avatar: require("../../public/imgs/12.jpg"),
          content: "告诉你什么最贵,你们女人的购物车。"
        },
        {
          isSelf: false, //是否是自己发送的消息
          avatar: require("../../public/imgs/mz.jpg"),
          content: "滚。。。"
        },
      ]
    }
  },
  methods: {
    sendMessage() {
      if (!this.msg) {
        return
      }
      this.$set(this.chatContentList, this.chatContentList.length, {
        isSelf: true, //是否是自己发送的消息
        avatar: require("../../public/imgs/12.jpg"),
        content: this.msg
      })
      this.msg = ""

      setTimeout(() => {
        this.$refs.chatContent.scrollTop = this.$refs.chatContent.scrollHeight
      }, 300);
    }
  }
}
</script>

<style lang="less" scoped>
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar
{
    width: 4px;
    height: 4px;
    background-color: transparent;
}
 
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track
{
    border-radius: 2px;
    background-color: transparent;
}
 
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb
{
    border-radius: 2px;
    background-color: transparent;
}

.draw-triangle {
  width: 100%;
  .title {
    padding: 12px 0;
    padding-left: 15px;
    font-size: 24px;
    font-weight: bold;
    line-height: 32px;
    position: relative;
    color: #409eff;
    &::after {
      content: "";
      width: 5px;
      height: 24px;
      background: #409eff;
      position: absolute;
      top: 50%;
      left: 0;
      transform: translateY(-50%);
    }
  }
  .mobile-box {
    width: 375px;
    height: 648px;
    margin: 0 auto;
    margin-top: 20px;
    position: relative;
    border: 1px solid #333;
    background: #e4e7ed;
    .header-box {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      line-height: 50px;
      text-align: center;
      background: #f2f2f2;
      z-index: 9;
      .back {
        position: absolute;
        top: 0;
        left: 0;
        width: 50px;
        height: 50px;
        .el-icon-arrow-left {
          font-size: 24px;
        }
      }
      .header-title {
        width: 100%;
        padding: 0 50px;
        color: #333;
        box-sizing: border-box;
        font-weight: bold;
        font-size: 16px;
      }
    }

    .input-box {
      width: 100%;
      height: 60px;
      position: absolute;
      bottom: 0;
      left: 0;
      background: #f2f2f2;
      .el-input {
        padding: 0 10px;
        padding-right: 50px;
        box-sizing: border-box;
        margin-top: 10px;
      }
      .right {
        position: absolute;
        right: 0;
        bottom: 0;
        width: 50px;
        height: 50px;
        text-align: center;
        line-height: 50px;
        .icon {
          font-size: 24px;
        }
      }
    }

    .content-box {
      width: 100%;
      padding-top: 50px;
      padding-bottom: 72px;
      height: 100%;
      box-sizing: border-box;
      overflow-y: auto;

      .chat-box {
        display: flex;
        margin-top: 12px;
        position: relative;
        &.right {
          justify-content: flex-end;
        }
        .avatar {
          position: absolute;
          top: 0;
          left: 10px;
          &.right {
            right: 10px;
            left: unset;
          }
          .avatar-img {
            width: 44px;
            height: 44px;
            border-radius: 4px;
          }
        }
        .chat-content {
          padding: 12px;
          background: #fff;
          border-radius: 10px;
          margin-left: 70px;
          margin-right: 70px;
          position: relative;
          border: 1px solid #ccc;
          &.right {
            border: none;
            background: #87d85f;
            &:before {
              content: "";
              right: -10px;
              left: unset;
              border-right: unset;
              border-left: 10px solid #87d85f;
            }
            &:after {
              content: "";
              right: -8px;
              left: unset;
              border-right: unset;
              border-left: 10px solid #87d85f;
            }
          }
          &:before {
            content: "";
            position: absolute;
            left: -10px;
            top: 16px;
            border-top: 6px solid transparent;
            border-bottom: 6px solid transparent;
            border-right: 10px solid #ccc;
          }
          &:after {
            content: "";
            position: absolute;
            left: -8px;
            top: 16px;
            border-top: 6px solid transparent;
            border-bottom: 6px solid transparent;
            border-right: 10px solid #fff;
          }
        }
      }
    }
  }
}
</style>
显示代码

# 注意

​ 上述聊天代码,如拿去升级仿各个平台聊天记录,后果自负。上述使用网络头像,如有侵权请告知,本人将及时撤销并更换头像。

# 总结

​ 总之,能用CSS实现的效果,坚决使用CSS。作者认为学好CSS是作为前端开发人员的重中之重。好的结构设计,能够让代码更加易维护。好好学习,天天向上。微信公众号【爆米花小布】等你来关注。

  1. 如何画出三角形【css】
  2. 如何滚动到底部【js】
  3. el-input如何使用原生事件 @keyup.native

友情链接

原文地址 (opens new window)

如何制作国旗头像 (opens new window)