侧边栏壁纸
博主头像
前端江太公博主等级

不知江月待何人

  • 累计撰写 178 篇文章
  • 累计创建 3 个标签
  • 累计收到 127 条评论
标签搜索

目 录CONTENT

文章目录
H5

CSS 的快乐:画一个可爱的三只小鸟 Button

前端江太公
2023-02-17 / 0 评论 / 1 点赞 / 569 阅读 / 92,500 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-02-17,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
广告 广告

做为前端工程师,最大的快乐之一就是可以用 CSS 画出各种有趣的效果。

比如我最近画的一个 Button:

动图封面

画的过程中确实很开心,这也是我当时选择做前端的很大一部分原因。

今天我们就一起来画下这个可爱的 Button 吧!纯 CSS,没用到图片和 JS 呦~

首先我们需要一些前置知识:

border-radius

border-radius 大家用的比较多了。

比如一个这样的 div:

#box {
    width: 100px;
    height: 100px;
    background: #f4cf47;
    border: solid 3px #000;
}

可以分别设置四个圆角的半径:

#box {
    border-radius: 20px 30px 40px 50px;
}

从效果上也可以看出来分别是左上、右上、左下、右下的圆角。

其实还可以设置椭圆角,椭圆和圆的区别是圆的半径都是一样的,而椭圆则是有长轴和短轴,可以不一样。

可以分别设置长半轴和短半轴的长度,用 / 隔开:

#box {
    border-radius: 20px 30px 40px 50px / 20px 30px 40px 50px;
}

当然,上面这个长短半轴相等了,也就是圆角了。

比如这样设置:

#box {
    border-radius: 20px 30px 40px 50px / 50px 40px 30px 20px;
}

效果是这样的:

分开看每个角:

左上角的横半轴是 20px,竖半轴是 50px,所以是这样的:

左下角横半轴是 40px,竖半轴是 30px,所以是这样的:

通过调整四个角的横竖半轴长度,就可以实现很多形状。

比如三只小鸟的睡觉时的形状:

或者醒的时候的形状:

还有鸟嘴和眼睛的形状:

当然,圆角能画的形状终究还是受限制的,更复杂的形状需要用别的方式来画,比如 clip-path:

clip-path

前面说过,整个按钮都没有用到图片,那按钮的这个背景:

还有这几根鸟毛:

怎么画呢?

border-radius?

border-radius 再怎么调也只是各种椭圆,没法画这种复杂形状。

想实现这些没有规律的复杂形状就要用到 cli-path 了。

比如这样一个 div:

 #box {
    width: 130px;
    height: 38px;
    background: blue;
}

加上这样一个 clip-path:

#box {
    clip-path : path('M13.77,37.35L.25,16.6c-.87-1.33,.69-2.91,2-2.02l12.67,8.59c.81,.55,1.91,.14,2.18-.81l2.62-9.33c.39-1.4,2.34-1.42,2.76-.02l3.6,11.99c.33,1.11,1.74,1.4,2.47,.52L49.38,.52c.87-1.04,2.53-.42,2.53,.95V23.7c0,1.13,1.2,1.83,2.16,1.26l12.75-7.51c.85-.5,1.94,0,2.13,.98l1.5,7.6c.2,1.03,1.37,1.51,2.22,.92l17.74-12.3c1.09-.75,2.52,.25,2.21,1.55l-2.44,10.2c-.26,1.09,.74,2.06,1.8,1.75l30.8-9.04c1.37-.4,2.42,1.26,1.49,2.36l-9.07,10.66c-.83,.98-.1,2.49,1.17,2.42l12.12-.68c1.6-.09,2.12,2.15,.65,2.8l-2.73,1.21c-.18,.08-.38,.12-.58,.12H14.97c-.48,0-.93-.25-1.2-.65Z') ;
}

就会变成这种形状:

或者这样一个 div:

#box {
    width: 12px;
    height: 12px;
    background: #000;
}

加上这样的 clip-path:

#box {
    clip-path : path('M10.23,3.32c-3.54,.63-5.72,2.51-7.02,4.23-.33-1.58-.34-3.54,.93-5.12,.52-.65,.41-1.59-.24-2.11C3.24-.19,2.29-.08,1.77,.57c-3.82,4.77-.31,11.11-.13,11.42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0-.01-.02,2.49,.04,2.52,0,.1-.14,1.54-4.82,6.59-5.71,.82-.14,1.37-.92,1.22-1.74s-.94-1.36-1.75-1.21Z') ;

}

就会变成这种形状:

背景和鸟毛不就出来了么~

这个样式还是很容易理解的,就像剪纸一样,把一块区域按照某个路径进行裁剪(svg 中也有这个)。

当然,不只可以写 path,还支持别的形状:

clip-path: circle(40%);
clip-path: ellipse(130px 140px at 10% 20%);
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
clip-path: path('M 0 200 L 0,75 A 5,5 0,0,1 150,75 L 200 200 z');

但是,这个形状怎么来呢?

手写么?

这肯定不靠谱。

其实是可以用 illustrator 等矢量图设计软件来画,导出为 svg 的。

比如 illustrator,用钢笔在左上角画一个形状:

选中它,然后点击“对象 > 复合路径 > 建立”:

再点击导出,这时候导出的就是带 path 的 svg。

有两点需要注意:

  • 要从左上角开始画,因为 svg 会把位移保存下来。
  • 没有复合路径那一步,导出的可能是 polygon、circle 这种形状,而不是 path

把路径复制到 cli-path 的样式处,就可以看到裁切后的效果了:

这样,涉及到的各种形状我们就都能画了。

再看一眼这个 Button:

动图封面

是不是就有思路了呢~

接下来我们动手画一下吧。

画 Button

先写出 html 的结构:

<a href="#" class="button button--bird">
<div class="button__wrapper">
<span class="button__text">ENTRY</span>
</div>
</a>

比一般的 button 多了一级,这是因为我们要通过每一级的 ::before 和 ::after 加一些伪元素。

设置 .button 的样式:

.button {
display: flex;
justify-content: center;
align-items: center;

<span class="k">box-sizing</span><span class="p">:</span> <span class="kc">border-box</span><span class="p">;</span>
<span class="k">width</span><span class="p">:</span> <span class="mi">280</span><span class="kt">px</span><span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">80</span><span class="kt">px</span><span class="p">;</span>

<span class="k">text-decoration</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span>
<span class="k">border</span><span class="p">:</span> <span class="kc">solid</span> <span class="mi">3</span><span class="kt">px</span> <span class="mh">#000</span><span class="p">;</span>
<span class="k">border-radius</span><span class="p">:</span> <span class="mi">40</span><span class="kt">px</span><span class="p">;</span>
<span class="k">background</span><span class="p">:</span> <span class="mh">#f4cf47</span><span class="p">;</span>

}

通过 flex 布局,让子元素居中。设置 width、height,背景颜色、圆角等。

现在效果是这样的:

其中的背景颜色可能会变,更好的方式是抽出一个变量来维护:

.button--bird {
--main_color: #f4cf47;
}
.button {
background : var(--main_color);
}

然后设置子元素的样式,也就是 .button__warpper:

.button__wrapper{
display: flex;
justify-content: center;
align-items: center;

<span class="k">width</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>

}

它同样要设置子元素居中,然后宽高都是 100%。

它的子元素就是 span 文本标签了,也就是 .button__text:

.button--bird {
--base_color: #000;
}
.button__text{
font-size: 32px;
letter-spacing: 4px;
color: var(--base_color);
}

指定字体大小、文字间距和颜色。颜色是可能会变的,所以也抽成变量。

现在的效果是这样的:

然后我们加上一些伪元素做装饰:

先给最外层元素加:

.button::before{
content: '';

<span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
<span class="k">right</span><span class="p">:</span> <span class="mi">20</span><span class="kt">px</span><span class="p">;</span>

<span class="k">margin</span><span class="p">:</span> <span class="kc">auto</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">width</span><span class="p">:</span> <span class="mi">24</span><span class="kt">px</span><span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">24</span><span class="kt">px</span><span class="p">;</span>

<span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">base_color</span><span class="p">);</span>
<span class="k">clip-path</span><span class="p">:</span> <span class="nf">path</span><span class="p">(</span><span class="s1">'M24,12.02c0-1.09-.75-1.71-.81-1.77L11.17,.45c-.91-.74-2.21-.56-2.91,.42-.69,.97-.52,2.37,.39,3.11l7.12,5.81-13.7-.02h0C.93,9.77,0,10.76,0,11.99c0,1.23,.93,2.22,2.07,2.22l13.7,.02-7.13,5.78c-.91,.74-1.09,2.13-.4,3.11,.41,.58,1.03,.88,1.65,.88,.44,0,.88-.15,1.25-.45l12.04-9.76c.07-.06,.82-.67,.82-1.77Z'</span><span class="p">);</span>

}

指定宽高和位置,还有背景颜色,再就是裁切的形状(这里用 clip-path 裁剪的是一个箭头的形状)

伪元素用了绝对定位,那元素就要相对定位:

.button {
position: relative;
}

也就是让伪元素相对它来偏移。

效果就是这样的:

然后再往里一层,给 .button__wrapper 加 ::before 和 ::after 伪元素:

.button--bird {
--sub_color1: #f4e19c;
}
.button--bird .button__wrapper::before,
.button--bird .button__wrapper::after{
content: '';

<span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
<span class="k">bottom</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>

<span class="k">width</span><span class="p">:</span> <span class="mi">130</span><span class="kt">px</span><span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">38</span><span class="kt">px</span><span class="p">;</span>

<span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">sub_color1</span><span class="p">);</span>

<span class="k">clip-path</span><span class="p">:</span> <span class="nf">path</span><span class="p">(</span><span class="s1">'M13.77,37.35L.25,16.6c-.87-1.33,.69-2.91,2-2.02l12.67,8.59c.81,.55,1.91,.14,2.18-.81l2.62-9.33c.39-1.4,2.34-1.42,2.76-.02l3.6,11.99c.33,1.11,1.74,1.4,2.47,.52L49.38,.52c.87-1.04,2.53-.42,2.53,.95V23.7c0,1.13,1.2,1.83,2.16,1.26l12.75-7.51c.85-.5,1.94,0,2.13,.98l1.5,7.6c.2,1.03,1.37,1.51,2.22,.92l17.74-12.3c1.09-.75,2.52,.25,2.21,1.55l-2.44,10.2c-.26,1.09,.74,2.06,1.8,1.75l30.8-9.04c1.37-.4,2.42,1.26,1.49,2.36l-9.07,10.66c-.83,.98-.1,2.49,1.17,2.42l12.12-.68c1.6-.09,2.12,2.15,.65,2.8l-2.73,1.21c-.18,.08-.38,.12-.58,.12H14.97c-.48,0-.93-.25-1.2-.65Z'</span><span class="p">);</span>

}

.button--bird .button__wrapper::before{
left: 0;
}
.button--bird .button__wrapper::after{
right: 0;
transform : rotateY(180deg) ;
}

分别在前后加上一个伪元素,设置宽高和背景色,裁切的形状。然后分别设置不同的位移,右边要反过来,所以是 rotateY(180deg)。

背景色也可能变,所以抽出一个变量。

这里伪元素用到了 position:absolute,同样要在元素上加上 position: relative;

.button__wrapper {
position: relative;
}

效果就是这样的:

然后我们先加一些 hover 的效果吧,毕竟也算一个完整的 Button 了。

hover 的时候,让字体间距变大,两个草丛背景分别左右移动,箭头往右移动:

.button:hover .button__text{
letter-spacing : 6px ;
}
.button:hover .button__wrapper::before{
transform : translateX(-12px) ;
}
.button:hover .button__wrapper::after{
transform : rotateY(180deg) translateX(-12px) ;
}
.button:hover::before{
right : 14px ;
}

效果是这样的:

动图封面

过渡有点太生硬了,设置下 transition:

.button__text {
transition: all .3s ease;
}
.button::before {
transition: all .2s ease;
}
.button__wrapper::before, .button__wrapper::after {
transition: all .5s ease;
}

文字 3s,箭头 2s,草丛 5s,都是匀速的过渡。

动图封面

这样就自然多了。

接下来就是最有意思的部分了:画三只小鸟。

在按钮的 div 的下方,再加一点 div:

<a href="#" class="button button--bird">
<div class="button__wrapper">
<span class="button__text">ENTRY</span>
</div>

<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"birdBox"</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird__face"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird__face"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird__face"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>

</a>

一个 birdBox 元素包含着 3 个 bird 的子元素,它还有一层子元素。

设置这些层当然也是为了利用每一层的 ::before、::after 来画一些东西:

先设置 .birdBox 的样式:

.birdBox {
position: absolute ;
top: -54px ;

<span class="k">display</span><span class="p">:</span> <span class="kc">flex</span> <span class="p">;</span>
<span class="k">justify-content</span><span class="p">:</span> <span class="kc">space</span><span class="o">-</span><span class="n">between</span> <span class="p">;</span>
<span class="k">align-items</span><span class="p">:</span> <span class="kc">flex</span><span class="o">-</span><span class="kc">end</span> <span class="p">;</span>

<span class="k">width</span><span class="p">:</span> <span class="mi">180</span><span class="kt">px</span> <span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">56</span><span class="kt">px</span> <span class="p">;</span>

}

设置宽高和绝对定位的位置,大概是在这里:

并且设置内容水平平分剩余空间,竖直居中。

然后设置子元素也就是每只小鸟的样式:

.bird{
width: 56px ;
height: 36px ;
box-sizing: border-box ;
border: solid 3px #000 ;
background: var(--main_color) ;
}

设置圆角:

.button__bird {
--border_radius1: 60px 60px 40px 40px / 48px 48px 30px 30px ;
}
.bird {
border-radius: var(--border_radius1) ;
}

这里也作为变量抽出来。

分别设置 4 个角的横竖半轴长度,调整得到这样的形状:

然后通过 ::before 伪元素画上鸟毛:

.bird {
position: relative;
}
.bird::before{
content: '' ;

<span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span> <span class="p">;</span>
<span class="k">top</span><span class="p">:</span> <span class="mi">-12</span><span class="kt">px</span> <span class="p">;</span>
<span class="k">left</span><span class="p">:</span> <span class="mi">22</span><span class="kt">px</span> <span class="p">;</span>

<span class="k">width</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span> <span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span> <span class="p">;</span>

<span class="k">background</span> <span class="p">:</span> <span class="mh">#000</span> <span class="p">;</span>
<span class="k">clip-path</span> <span class="p">:</span> <span class="nf">path</span><span class="p">(</span><span class="s1">'M10.23,3.32c-3.54,.63-5.72,2.51-7.02,4.23-.33-1.58-.34-3.54,.93-5.12,.52-.65,.41-1.59-.24-2.11C3.24-.19,2.29-.08,1.77,.57c-3.82,4.77-.31,11.11-.13,11.42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0-.01-.02,2.49,.04,2.52,0,.1-.14,1.54-4.82,6.59-5.71,.82-.14,1.37-.92,1.22-1.74s-.94-1.36-1.75-1.21Z'</span><span class="p">)</span> <span class="p">;</span>

}

这种不规则形状当然也是通过 clip-path 裁剪出来的。

然后再画上嘴:

在子元素 .bird__face 上画:

.button--bird{
--sub_color2: #ff8108 ;
}
.bird__face{
position: absolute ;
top: 15px ;

<span class="k">width</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span> <span class="p">;</span>
<span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span> <span class="p">;</span>

<span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">sub_color2</span><span class="p">)</span> <span class="p">;</span>
<span class="k">border-radius</span><span class="p">:</span> <span class="mi">50</span><span class="kt">%</span> <span class="mi">50</span><span class="kt">%</span> <span class="mi">50</span><span class="kt">%</span> <span class="mi">50</span><span class="kt">%</span> <span class="o">/</span> <span class="mi">78</span><span class="kt">%</span> <span class="mi">78</span><span class="kt">%</span> <span class="mi">22</span><span class="kt">%</span> <span class="mi">22</span><span class="kt">%</span> <span class="p">;</span>

}

设置宽高和定位,背景颜色和圆角,就可以得到鸟嘴:

要居中的话可以在它的父元素设置 display: flex:

.bird {
display: flex;
justify-content: center;
}

然后再通过 ::before 和 ::after 伪元素来画两只眼睛:

.bird__face::before,
.bird__face::after{
content: '' ;
position: absolute ;
top: -4px ;
width: 8px ;

<span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span> <span class="p">;</span>
<span class="k">border-radius</span><span class="p">:</span> <span class="mi">4</span><span class="kt">px</span> <span class="p">;</span>
<span class="k">background</span><span class="p">:</span> <span class="mh">#000</span> <span class="p">;</span>

}
.bird__face::before{
left: -5px ;
}
.bird__face::after{
right: -5px ;
}

设置定位、宽高、位置、圆角、背景颜色即可:

至此,睡着的小鸡就画完了!

核心就是就是元素和伪元素通过定位 + flex 来布局,然后通过 border-radius 和 clip-path 设置形状。

接下来画睡醒以后的小鸡:

只有前两只会醒,所以给它俩单独加个 wakeup 的 class:

<div class="birdBox">
<div class="bird wakeup">
<div class="bird__face"></div>
</div>
<div class="bird wakeup">
<div class="bird__face"></div>
</div>
<div class="bird">
<div class="bird__face"></div>
</div>
</div>

当 hover 的时候,wakeup 的小鸡会执行伸展身体的动画:

动图封面

这个动画里变的是什么呢?

明显是 height 变了,我们设置下:

.button:hover .wakeup{
animation: wakeup .2s ease ;
}

@keyframes wakeup{
0% {
height : 32px;
}
100%{
height : 56px ;
}
}

动图封面

这样有两个问题,一个是动画没有停住,一执行完就回去了,这个可以设置 animation-fill-mode 来解决:

.button:hover .wakeup{
animation : wakeup .2s ease ;
animation-fill-mode : forwards ;
}

设置 animation-fill-mode 为 forwards 就是停留在最后一帧的意思:

动图封面

还有一个问题就是鸟高度变大后,圆角也得重新设置下,不然形状很奇怪:

.button--bird {
--border_radius2: 70px 70px 40px 40px / 48px 48px 30px 30px ;
--border_radius3: 40px 40px 40px 40px / 48px 48px 30px 30px ;
}
@keyframes wakeup{
0% {
height: 32px;
border-radius: var(--border_radius2) ;
}
100%{
height: 56px ;
border-radius: var(--border_radius3) ;
}
}

这样就好多了:

动图封面

再就是醒来以后眼睛也得睁开,还要眨眼,这个怎么做呢?

看下分解动作就明白了:

.button:hover .wakeup .bird__face::before,
.button:hover .wakeup .bird__face::after{
width: 6px;
height: 6px;
}

设置宽高都为 6px,这样就是睁开眼睛的效果:

动图封面

瞬间变精神小伙。

这样是之前闭着眼睛的效果:

.button:hover .wakeup .bird__face::before,
.button:hover .wakeup .bird__face::after{
width: 8px;
height: 2px;
}
动图封面

连起来设置几个关键帧,那就是眨眼动画了:

 @keyframes eye {
0%{
top : -6px ;
width : 6px ;
height : 6px ;
}
30%{
top : -6px ;
width : 6px ;
height : 6px ;
}
32%{
top : -4px ;
width : 8px ;
height : 2px ;
}
34%{
top : -6px ;
width : 6px ;
height : 6px ;
}
70%{
top : -6px ;
width : 6px ;
height : 6px ;
}
72%{
top : -4px ;
width : 8px ;
height : 2px ;
}
74%{
top : -6px ;
width : 6px ;
height : 6px ;
}
76%{
top : -4px ;
width : 8px ;
height : 2px ;
}
78%{
top : -6px ;
width : 6px ;
height : 6px ;
}
100%{
top : -6px ;
width : 6px ;
height : 6px ;
}
}

当然睁眼以后高度变高,top 也得调整下。

然后应用这个动画:

.button:hover .wakeup .bird__face::before,
.button:hover .wakeup .bird__face::after{
animation : eye 5s linear infinite ;
}

5s 内匀速执行动画,无限次执行。

试一下:

动图封面

瞬间就有灵气了。

都一样的动作显得有点呆,我们让第二只鸟往右边看一下。

也就是这样的动画:

@keyframes eye_2 {
0%{
top : -6px ;
width : 6px ;
height : 6px ;
}
10%{
transform : translateX(0);
}
12%{
transform : translateX(3px);
}
20%{
top : -6px ;
width : 6px ;
height : 6px ;
}
22%{
top : -4px ;
width : 8px ;
height : 2px ;
}
24%{
top : -6px ;
width : 6px ;
height : 6px ;
}
25%{
transform : translateX(3px);
}
27%{
transform : translateX(0);
}
74%{
top : -6px ;
width : 6px ;
height : 6px ;
transform : translateX(0);
}
76%{
top : -4px ;
width : 8px ;
height : 2px ;
transform : translateX(3px);
}
78%{
top : -6px ;
width : 6px ;
height : 6px ;
}
80%{
top : -4px ;
width : 8px ;
height : 2px ;
}
82%{
top : -6px ;
width : 6px ;
height : 6px ;
}
85%{
transform : translateX(3px);
}
87%{
transform : translateX(0);
}
100%{
top : -6px ;
width : 6px ;
height : 6px ;
transform : translateX(0);
}

}

就是多了一个 translateX 的位移。

给第二支鸟应用这个动画:

.button:hover .wakeup:nth-child(2) .bird__face::before,
.button:hover .wakeup:nth-child(2) .bird__face::after{
animation : eye_2 5s linear infinite ;
}

再来试下:

动图封面

更可爱了一点!

最后,还要做一个睡着的动画,睡着的时候随着呼吸,身体也是有起伏的,这个动画也是改 height 和 border-radius:

.button__bird {
--border_radius1 : 60px 60px 40px 40px / 48px 48px 30px 30px ;
--border_radius2 : 70px 70px 40px 40px / 48px 48px 30px 30px ;
}
@keyframes sleep{
0% {
height: 36px ;
border-radius: var(--border_radius1) ;
}
100%{
height: 32px ;
border-radius: var(--border_radius2) ;
}
}
.bird {
animation: sleep 1s ease infinite alternate;
}

先试一下:

动图封面

确实有随着呼吸身体起伏的感觉了!

但不知道同学们有没有发现这个动画的不同之处?

我们多设置了个 alternate,这个是 animation-direction,动画方向的意思。

如果不设置是这样的效果:

动图封面

每次都从低到高来运动。

但应该是低到高、高到低、低到高这样的循环往复的运动。

animation-direction: alternate 的效果就是正向、反向、正向、反向这样循环。

当然它也有别的取值:

  • normal:正向:
  • reverse:反向
  • alternate:正向、反向、正向、反向...
  • alternate-reverse:反向、正向、反向、正向...

至此,这个可爱的 Button 就完成了,我们整体感受一下:

动图封面

确实很可爱!

全部代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<a href="#" class="button button--bird">
<div class="button__wrapper">
<span class="button__text">ENTRY</span>
</div>

    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"birdBox"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird wakeup"</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird__face"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird wakeup"</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird__face"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird"</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"bird__face"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">style</span><span class="p">&gt;</span>
    <span class="nt">body</span> <span class="p">{</span>
        <span class="k">padding</span><span class="p">:</span> <span class="mi">100</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button--bird</span><span class="p">{</span>
        <span class="nv">--main_color</span><span class="p">:</span> <span class="mh">#f4cf47</span><span class="p">;</span>
        <span class="nv">--sub_color1</span><span class="p">:</span> <span class="mh">#f4e19c</span><span class="p">;</span>
        <span class="nv">--sub_color2</span><span class="p">:</span> <span class="mh">#ff8108</span><span class="p">;</span>
        <span class="nv">--base_color</span><span class="p">:</span> <span class="mh">#000</span><span class="p">;</span>
        <span class="nv">--border_radius1</span><span class="p">:</span> <span class="mi">60</span><span class="kt">px</span> <span class="mi">60</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="o">/</span> <span class="mi">48</span><span class="kt">px</span> <span class="mi">48</span><span class="kt">px</span> <span class="mi">30</span><span class="kt">px</span> <span class="mi">30</span><span class="kt">px</span><span class="p">;</span>
        <span class="nv">--border_radius2</span><span class="p">:</span> <span class="mi">70</span><span class="kt">px</span> <span class="mi">70</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="o">/</span> <span class="mi">48</span><span class="kt">px</span> <span class="mi">48</span><span class="kt">px</span> <span class="mi">30</span><span class="kt">px</span> <span class="mi">30</span><span class="kt">px</span><span class="p">;</span>
        <span class="nv">--border_radius3</span><span class="p">:</span> <span class="mi">40</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="mi">40</span><span class="kt">px</span> <span class="o">/</span> <span class="mi">48</span><span class="kt">px</span> <span class="mi">48</span><span class="kt">px</span> <span class="mi">30</span><span class="kt">px</span> <span class="mi">30</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span> <span class="p">{</span>
        <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
        <span class="k">justify-content</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
        <span class="k">align-items</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>

        <span class="k">box-sizing</span><span class="p">:</span> <span class="kc">border-box</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">280</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">80</span><span class="kt">px</span><span class="p">;</span>

        <span class="k">text-decoration</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span>
        <span class="k">border</span><span class="p">:</span> <span class="kc">solid</span> <span class="mi">3</span><span class="kt">px</span> <span class="mh">#000</span><span class="p">;</span>
        <span class="k">border-radius</span><span class="p">:</span> <span class="mi">40</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">main_color</span><span class="p">);</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">relative</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">{</span>
        <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
        <span class="k">justify-content</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
        <span class="k">align-items</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>

        <span class="k">width</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>

        <span class="k">border-radius</span><span class="p">:</span> <span class="mi">40</span><span class="kt">px</span><span class="p">;</span>

        <span class="k">overflow</span><span class="p">:</span> <span class="kc">hidden</span><span class="p">;</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">relative</span><span class="p">;</span>

    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button__text</span><span class="p">{</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">relative</span><span class="p">;</span>
        <span class="k">font-size</span><span class="p">:</span> <span class="mi">32</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">letter-spacing</span><span class="p">:</span> <span class="mi">4</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">base_color</span><span class="p">);</span>
        <span class="k">transition</span><span class="p">:</span> <span class="kc">all</span> <span class="mf">.3</span><span class="kt">s</span> <span class="kc">ease</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">.</span><span class="nc">button</span><span class="p">::</span><span class="nd">before</span><span class="p">{</span>
        <span class="k">content</span><span class="p">:</span> <span class="s1">''</span><span class="p">;</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>

        <span class="k">right</span><span class="p">:</span> <span class="mi">20</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">margin</span><span class="p">:</span> <span class="kc">auto</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">24</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">24</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">base_color</span><span class="p">);</span> 
        <span class="k">clip-path</span><span class="p">:</span> <span class="nf">path</span><span class="p">(</span><span class="s1">'M24,12.02c0-1.09-.75-1.71-.81-1.77L11.17,.45c-.91-.74-2.21-.56-2.91,.42-.69,.97-.52,2.37,.39,3.11l7.12,5.81-13.7-.02h0C.93,9.77,0,10.76,0,11.99c0,1.23,.93,2.22,2.07,2.22l13.7,.02-7.13,5.78c-.91,.74-1.09,2.13-.4,3.11,.41,.58,1.03,.88,1.65,.88,.44,0,.88-.15,1.25-.45l12.04-9.76c.07-.06,.82-.67,.82-1.77Z'</span><span class="p">);</span>
        <span class="k">transition</span><span class="p">:</span> <span class="kc">all</span> <span class="kc">ease</span> <span class="mf">.2</span><span class="kt">s</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button--bird</span> <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">::</span><span class="nd">before</span><span class="o">,</span>
    <span class="p">.</span><span class="nc">button--bird</span> <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">content</span><span class="p">:</span> <span class="s1">''</span><span class="p">;</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
        <span class="k">bottom</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">130</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">38</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">sub_color1</span><span class="p">);</span>
        <span class="k">transition</span><span class="p">:</span> <span class="kc">all</span> <span class="mf">.5</span><span class="kt">s</span> <span class="kc">ease</span><span class="p">;</span>
        <span class="k">clip-path</span><span class="p">:</span> <span class="nf">path</span><span class="p">(</span><span class="s1">'M13.77,37.35L.25,16.6c-.87-1.33,.69-2.91,2-2.02l12.67,8.59c.81,.55,1.91,.14,2.18-.81l2.62-9.33c.39-1.4,2.34-1.42,2.76-.02l3.6,11.99c.33,1.11,1.74,1.4,2.47,.52L49.38,.52c.87-1.04,2.53-.42,2.53,.95V23.7c0,1.13,1.2,1.83,2.16,1.26l12.75-7.51c.85-.5,1.94,0,2.13,.98l1.5,7.6c.2,1.03,1.37,1.51,2.22,.92l17.74-12.3c1.09-.75,2.52,.25,2.21,1.55l-2.44,10.2c-.26,1.09,.74,2.06,1.8,1.75l30.8-9.04c1.37-.4,2.42,1.26,1.49,2.36l-9.07,10.66c-.83,.98-.1,2.49,1.17,2.42l12.12-.68c1.6-.09,2.12,2.15,.65,2.8l-2.73,1.21c-.18,.08-.38,.12-.58,.12H14.97c-.48,0-.93-.25-1.2-.65Z'</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button--bird</span> <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">::</span><span class="nd">before</span><span class="p">{</span>
        <span class="k">left</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button--bird</span> <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">right</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">transform</span><span class="p">:</span> <span class="nb">rotateY</span><span class="p">(</span><span class="mi">180</span><span class="kt">deg</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">::</span><span class="nd">before</span><span class="p">{</span>
        <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">-12</span><span class="kt">px</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">button__wrapper</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">transform</span><span class="p">:</span> <span class="nb">rotateY</span><span class="p">(</span><span class="mi">180</span><span class="kt">deg</span><span class="p">)</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">-12</span><span class="kt">px</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">button__text</span><span class="p">{</span>
        <span class="k">letter-spacing</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span><span class="p">::</span><span class="nd">before</span><span class="p">{</span>
        <span class="k">right</span><span class="p">:</span> <span class="mi">14</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="p">.</span><span class="nc">birdBox</span><span class="p">{</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
        <span class="k">top</span><span class="p">:</span> <span class="mi">-54</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
        <span class="k">justify-content</span><span class="p">:</span><span class="kc">space</span><span class="o">-</span><span class="n">between</span><span class="p">;</span>
        <span class="k">align-items</span><span class="p">:</span> <span class="kc">flex</span><span class="o">-</span><span class="kc">end</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">180</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">56</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">.</span><span class="nc">bird</span><span class="p">{</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">relative</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">56</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">36</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">box-sizing</span><span class="p">:</span> <span class="kc">border-box</span><span class="p">;</span>
        <span class="k">border</span><span class="p">:</span> <span class="kc">solid</span> <span class="mi">3</span><span class="kt">px</span> <span class="mh">#000</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">main_color</span><span class="p">);</span>
        <span class="k">border-radius</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">border_radius1</span><span class="p">);</span>
        <span class="k">animation</span><span class="p">:</span> <span class="n">sleep</span> <span class="mi">1</span><span class="kt">s</span> <span class="kc">ease</span> <span class="kc">infinite</span> <span class="kc">alternate</span><span class="p">;</span>
        <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
        <span class="k">justify-content</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">bird__face</span><span class="p">{</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
        <span class="k">top</span><span class="p">:</span> <span class="mi">15</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">sub_color2</span><span class="p">);</span>
        <span class="k">border-radius</span><span class="p">:</span> <span class="mi">50</span><span class="kt">%</span> <span class="mi">50</span><span class="kt">%</span> <span class="mi">50</span><span class="kt">%</span> <span class="mi">50</span><span class="kt">%</span> <span class="o">/</span> <span class="mi">78</span><span class="kt">%</span> <span class="mi">78</span><span class="kt">%</span> <span class="mi">22</span><span class="kt">%</span> <span class="mi">22</span><span class="kt">%</span><span class="p">;</span>
        <span class="k">transition</span><span class="p">:</span> <span class="mf">.2</span><span class="kt">s</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">before</span><span class="o">,</span>
    <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">content</span><span class="p">:</span> <span class="s1">''</span><span class="p">;</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
        <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">border-radius</span><span class="p">:</span> <span class="mi">4</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="mh">#000</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">before</span><span class="p">{</span>
        <span class="k">left</span><span class="p">:</span> <span class="mi">-5</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">right</span><span class="p">:</span> <span class="mi">-5</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">bird</span><span class="p">::</span><span class="nd">before</span><span class="p">{</span>
        <span class="k">content</span><span class="p">:</span> <span class="s1">''</span><span class="p">;</span>
        <span class="k">position</span><span class="p">:</span> <span class="kc">absolute</span><span class="p">;</span>
        <span class="k">top</span><span class="p">:</span> <span class="mi">-12</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">left</span><span class="p">:</span> <span class="mi">22</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">width</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">height</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</span><span class="p">;</span>
        <span class="k">background</span><span class="p">:</span> <span class="mh">#000</span><span class="p">;</span>
        <span class="k">clip-path</span><span class="p">:</span> <span class="nf">path</span><span class="p">(</span><span class="s1">'M10.23,3.32c-3.54,.63-5.72,2.51-7.02,4.23-.33-1.58-.34-3.54,.93-5.12,.52-.65,.41-1.59-.24-2.11C3.24-.19,2.29-.08,1.77,.57c-3.82,4.77-.31,11.11-.13,11.42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0-.01-.02,2.49,.04,2.52,0,.1-.14,1.54-4.82,6.59-5.71,.82-.14,1.37-.92,1.22-1.74s-.94-1.36-1.75-1.21Z'</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">wakeup</span><span class="p">{</span>
        <span class="k">animation</span><span class="p">:</span> <span class="n">wakeup</span> <span class="mf">.2</span><span class="kt">s</span> <span class="kc">ease</span><span class="p">;</span>
        <span class="k">animation-fill-mode</span><span class="p">:</span> <span class="kc">forwards</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">wakeup</span> <span class="p">.</span><span class="nc">bird__face</span><span class="p">{</span>
        <span class="k">top</span><span class="p">:</span> <span class="mi">20</span><span class="kt">px</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">wakeup</span> <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">before</span><span class="o">,</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">wakeup</span> <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">animation</span><span class="p">:</span> <span class="n">eye</span> <span class="mi">5</span><span class="kt">s</span> <span class="kc">linear</span> <span class="kc">infinite</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">wakeup</span><span class="p">:</span><span class="nd">nth-child</span><span class="o">(</span><span class="nt">2</span><span class="o">)</span> <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">before</span><span class="o">,</span>
    <span class="p">.</span><span class="nc">button</span><span class="p">:</span><span class="nd">hover</span> <span class="p">.</span><span class="nc">wakeup</span><span class="p">:</span><span class="nd">nth-child</span><span class="o">(</span><span class="nt">2</span><span class="o">)</span> <span class="p">.</span><span class="nc">bird__face</span><span class="p">::</span><span class="nd">after</span><span class="p">{</span>
        <span class="k">animation</span><span class="p">:</span> <span class="n">eye_2</span> <span class="mi">5</span><span class="kt">s</span> <span class="kc">linear</span> <span class="kc">infinite</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="p">@</span><span class="k">keyframes</span> <span class="nt">wakeup</span><span class="p">{</span>
        <span class="nt">0</span><span class="o">%</span>  <span class="p">{</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">32</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">border-radius</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">border_radius2</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">100</span><span class="o">%</span><span class="p">{</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">56</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">border-radius</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">border_radius3</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="p">@</span><span class="k">keyframes</span> <span class="nt">eye</span> <span class="p">{</span>
        <span class="nt">0</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">30</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">32</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">34</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">70</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">72</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">74</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">76</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">78</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">100</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="p">@</span><span class="k">keyframes</span> <span class="nt">eye_2</span> <span class="p">{</span>
        <span class="nt">0</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">10</span><span class="o">%</span><span class="p">{</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">12</span><span class="o">%</span><span class="p">{</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">3</span><span class="kt">px</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">20</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">22</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">24</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">25</span><span class="o">%</span><span class="p">{</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">3</span><span class="kt">px</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">27</span><span class="o">%</span><span class="p">{</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">74</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">76</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">3</span><span class="kt">px</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">78</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">80</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-4</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">82</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="nt">85</span><span class="o">%</span><span class="p">{</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">3</span><span class="kt">px</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">87</span><span class="o">%</span><span class="p">{</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">100</span><span class="o">%</span><span class="p">{</span>
            <span class="k">top</span><span class="p">:</span> <span class="mi">-6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">width</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">transform</span><span class="p">:</span> <span class="nb">translateX</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        
    <span class="p">}</span>
    <span class="p">@</span><span class="k">keyframes</span> <span class="nt">sleep</span><span class="p">{</span>
        <span class="nt">0</span><span class="o">%</span>  <span class="p">{</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">36</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">border-radius</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">border_radius1</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="nt">100</span><span class="o">%</span><span class="p">{</span>
            <span class="k">height</span><span class="p">:</span> <span class="mi">32</span><span class="kt">px</span><span class="p">;</span>
            <span class="k">border-radius</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">border_radius2</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span>

</body>
</html>

总结

我们通过纯 CSS 实现了一个可爱的 Button,核心就是用元素 + 伪元素通过 flex + 定位来布局,然后通过 border-radius + clip-path 设置形状,通过 animation + @keyframes 来做复杂的动画,通过 transition 设置过渡效果。

border-radius 可以设置 4 个角的横竖半轴的长度,从而做出很多形状,更复杂的不规则形状可以通过 clip-path 来裁剪出来。

其中要注意的是可以通过设置 animnation-fill-mode: forwards 让动画停在最后一帧,设置 animation-direction: alternate 可以正反交替执行动画。再就是最好通过变量把会变化的样式值提取出来,这样方便配置。

用 CSS 实现一些有趣的效果确实感觉很好,这也是前端工程师专属的快乐。

1
广告 广告

评论区