单个div标签实现发呆表情

1,086 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

看到微信聊天中的表情很有趣,于是尝试使用一个标签和css去实现发呆的表情,本文记叙了实现的思路。
微信表情原图:

微信截图_20220612215335.png

效果

基本思路

可以看到表情中的元素还是比较多的,有眼睛(眼白,瞳孔)、腮红、嘴巴、眉毛这些。
虽然看上去元素挺多的,但是仔细看去,其实就是两个形状,眼睛、腮红、嘴巴都是原型,就眉毛是两条不同方向的直线,都是比较简单的图形。
那么思路就很简单了,无非就是实现这两个图形。但是元素不够如何处理,div加上两个伪元素,勉强算是三个标签,不够实现表情的所有元素。这个时候就需要box-shadow来帮忙了,它可以重复元素的形状并且自定义位置,最主要的是,阴影可以存在多个。

代码

HTML布局

这个没什么好说的,就一个div

<div class="daze"></div>

样式

  1. 首先从脸开始,很简单的一个圆,设定好其宽度和高度,还有border-radius,加上肤色,代码如下:
.daze {
  width: 100px;
  height: 100px;
  background: radial-gradient(rgb(247, 229, 126), rgb(246, 212, 65));
  border-radius: 50%;
  position: relative;
}

加上样式可以看到一个大圆脸:

微信截图_20220612220340.png

  1. 然后是脸上部件,先把那些圆形的处理起来,包括眼睛,嘴巴,腮红;先使用::before画一个瞳孔,顺便固定其位置:
.daze::before {
  content: '';
  width: 15px;
  height: 15px;
  background: #000;
  border-radius: 50%;
  /* 使用绝对定位调整位置 */
  position: absolute;
  top: 35px;
  left: 20px;
}

微信截图_20220612220736.png
然后就是使用最主要的box-shadow,先用它原地画一个眼白,注意不要设置模糊程度

/* 眼睛和嘴巴 */
.daze::before {
  content: '';
  width: 15px;
  height: 15px;
  background: #000;
  border-radius: 50%;
  position: absolute;
  top: 35px;
  left: 20px;
  // 设定阴影
  box-shadow: 0px 0px 0 10px #fff;
}

微信截图_20220612221202.png
一只眼睛就基本画出来了,用同样的阴影处理就可以画出第二只眼睛,不过要注意的位置的调整,两只眼睛是轴对称的,所以要确定好位置。
因为在本文中设定脸的宽度为100px,瞳孔为15px,位置上left: 20px,所以,另一个眼睛在x轴上的相对距离为脸宽度 - 两个瞳孔宽度及它们距离左右边界的距离 + 左侧瞳孔宽度100px - (15px + 20px) * 2 + 15px = 45px,距离算好,自然是添加阴影,把另一个眼睛画出来:

box-shadow:
    0px 0px 0 10px #fff,
    45px 0px #000,
    45px 0px 0 10px #fff;

微信截图_20220612222152.png
用同样的思路和方法,画出腮红和嘴巴,需要注意的是,除了腮红需要模糊之外,其他元素都不需要模糊,完整的box-shadow设置如下:

box-shadow:
    /* 第一只眼睛眼白 */
    0px 0px 0 10px #fff,
    /* 第二只眼睛的瞳孔和眼白 */
    45px 0px #000,
    45px 0px 0 10px #fff,
    /* 嘴巴 */
    22.5px 30px rgb(200, 135, 48),
    /* 两侧的腮红,需要模糊 */
    -12px 15px 15px 5px rgba(244, 117, 17, 0.6),
    57px 15px 15px 5px rgba(244, 117, 17, 0.6);

微信截图_20220612222632.png

  1. 最后就是眉毛,只剩下一个::after伪元素了,但是无法再和上面一样使用box-shadow复制形状的做法了,因为box-shadow只能复制元素本身的形状,虽然两边的眉毛形状相同,但是指向方向不同。
    最终的决解方法就是,将::after设置成为菱形,旋转45deg,放在眼睛中间:
.daze::after {
  content: '';
  position: absolute;
  width: 40px;
  height: 40px;
  top: -10px;
  left: 30px;
  background: rgb(158, 112, 58);
  // 设置旋转和倾斜
  transform: rotateZ(45deg) skew(-10deg, -10deg);
}

微信截图_20220612223345.png
然后不是使用阴影复制形状了,而是普通地使用阴影分别向两个红色箭头的指向露出一点阴影,使其看起来像两条眉毛,然后将::after本身设置为透明,最终样式为:

.daze::after {
  content: '';
  position: absolute;
  width: 40px;
  height: 40px;
  top: -10px;
  left: 30px;
  background: transparent;
  transform: rotateZ(45deg) skew(-10deg, -10deg);
  box-shadow: 0px 3px rgb(158, 112, 58), 3px 0 rgb(158, 112, 58);
}

微信截图_20220612223737.png