介绍
Hello,掘友们好!又是一年新春之际,祝福大家兔年快乐!下面我们使用纯 CSS 制作一个兔子、气球动画,效果为:一个圆形框内有只兔子,当我们在光标悬停在圆形框内或通过键盘 Tab 键导航来聚焦到圆形框元素时,小兔子将张大嘴巴,同时底部升起三只不同颜色的气球,上面的祝福语也会开启颜色动画,这个动效意味着掘友们能在新年大展宏图、步步高升。
实现
- 创建一个容器元素。 - 1 - <div class="container" tabindex="0"></div> - 设置 tabindex=”0”,表示该容器元素是可聚焦的,并且可以通过键盘 Tab 键导航来聚焦到该元素。 
- 创建顶部祝福语元素。 - 1 - <div class="prompt">大展宏兔 步步高升</div> - 由于是在容器元素状态变化时,改变祝福语元素的状态,所以可以使用相邻兄弟选择器 +,且要将它们 position 属性设置为 absolute,从而将容器元素排在后面显示。祝福语元素的动画状态默认 paused,当容器元素 hover 和 focus 时,动画状态变为 running。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47- div { 
 position: absolute;
 }
 .prompt {
 top: 0;
 left: 0;
 right: 0;
 margin: 0 auto;
 text-align: center;
 padding: 1em;
 font-size: calc(1em + 1.5vw);
 font-weight: bold;
 background: linear-gradient(150deg, #9b5de5 0%, #f15bb5 20%, #fee440 40%, #00bbf9 60%, #00f5d4 80%);
 background-size: 20% 20%;
 background-color: #840b2a;
 -webkit-background-clip: text;
 -webkit-text-fill-color: transparent;
 animation: gradient 5s linear infinite paused;
 }
 @keyframes gradient {
 0% {
 background-position: 0% 0%;
 }
 50% {
 background-position: 50% 50%;
 }
 100% {
 background-position: 100% 100%;
 }
 }
 .container {
 top: 6em;
 bottom: 0;
 left: 0;
 right: 0;
 margin: 0 auto;
 width: 24em;
 height: 24em;
 background: aquamarine;
 border-radius: 50%;
 border: 1em solid #b2ffe5;
 overflow: hidden;
 filter: brightness(.9);
 }
 .container:hover+.prompt, .container:focus+.prompt {
 animation-play-state: running;
 }
- 创建兔子身体各个位置的元素。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- <!-- 身体 --> 
 <div class="body">
 <!-- 眼睛 -->
 <div class="eye left">
 <div class="shine"></div>
 </div>
 <div class="eye right">
 <div class="shine"></div>
 </div>
 <!-- 鼻子 -->
 <div class="nose"></div>
 <!-- 嘴巴 -->
 <div class="mouth"></div>
 </div>
 <!-- 耳朵 -->
 <div class="ear-left">
 <div class="inner-ear-left"></div>
 </div>
 <div class="ear-right">
 <div class="inner-ear-right"></div>
 </div>- 设置兔子身体各个位置的元素样式,当容器元素 hover 和 focus 时,设置嘴巴元素高度变化。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123- .body { 
 top: 12em;
 bottom: 0;
 left: 0;
 right: 0;
 margin: 0 auto;
 width: 14em;
 height: 12em;
 border-radius: 6.5em 6.5em 5em 5em;
 background: #F2F2F2;
 z-index: 50;
 }
 .eye {
 top: 4em;
 width: 3em;
 height: 3em;
 background: #2E2E2E;
 border-radius: 50%;
 z-index: 100;
 }
 .left {
 left: 3em;
 }
 .right {
 right: 3em;
 }
 .shine {
 top: 0.22em;
 left: 0.22em;
 width: 1.5em;
 height: 1.5em;
 border-radius: 50%;
 background: white;
 }
 .nose {
 left: 0;
 right: 0;
 margin: 0 auto;
 top: 7.5em;
 width: 1.9em;
 height: 1.1em;
 border-radius: 50% 50% 35% 35%;
 background: pink;
 z-index: 960;
 }
 .mouth {
 z-index: 950;
 }
 .mouth-left {
 background: #fff;
 width: 2.6em;
 height: 2em;
 border-radius: 50%;
 top: 7.8em;
 left: 4.7em;
 }
 .mouth-right {
 background: #fff;
 width: 2.6em;
 height: 2em;
 border-radius: 50%;
 top: 7.8em;
 left: 6.7em;
 }
 .ear-left {
 background: #F2F2F2;
 height: 14em;
 width: 4em;
 border-radius: 50%;
 left: 6em;
 top: 1.6em;
 transform: rotate(-10deg);
 z-index: 10;
 }
 .inner-ear-left {
 left: 0;
 right: 0;
 margin: 0 auto;
 background: #fff;
 height: 10em;
 width: 2.6em;
 border-radius: 50%;
 top: 3em;
 }
 .ear-right {
 background: #F2F2F2;
 height: 14em;
 width: 4em;
 border-radius: 50%;
 right: 6em;
 top: 1.6em;
 transform: rotate(10deg);
 z-index: 10;
 }
 .inner-ear-right {
 left: 0;
 right: 0;
 margin: 0 auto;
 background: #fff;
 height: 10em;
 width: 2.6em;
 border-radius: 50%;
 top: 3em;
 }
 .mouth {
 top: 9.6em;
 left: 0;
 right: 0;
 margin: 0 auto;
 border-radius: 0 0 5em 5em;
 width: 2em;
 height: .6em;
 background: pink;
 z-index: 900;
 transition: height 500ms ease-in-out;
 }
 .container:hover, .container:focus {
 filter: brightness(1);
 outline: 0;
 }
 .container:hover>.body>.mouth, .container:focus>.body>.mouth {
 height: 1.6em;
 }
- 创建各个气球元素。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- <div class="balloon-1"> 
 <div class="inner-balloon-1"></div>
 <div class="knot-1"></div>
 <div class="line-1"></div>
 </div>
 <div class="balloon-2">
 <div class="inner-balloon-2"></div>
 <div class="knot-2"></div>
 <div class="line-2"></div>
 </div>
 <div class="balloon-3">
 <div class="inner-balloon-3"></div>
 <div class="knot-3"></div>
 <div class="line-3"></div>
 </div>- 设置各个气球元素样式,当容器元素 hover 和 focus 时,开启气球从底部升起动画。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125- .balloon-1 { 
 background: red;
 width: 6.6em;
 height: 8em;
 left: 2em;
 top: 24em;
 border-radius: 50%;
 z-index: 0;
 }
 .inner-balloon-1 {
 background: white;
 opacity: 0.3;
 width: 5.6em;
 height: 7em;
 left: 0em;
 top: 0em;
 border-radius: 50%;
 }
 .knot-1 {
 background: red;
 clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
 width: 1em;
 height: 1em;
 top: 7.6em;
 left: 0;
 right: 0;
 margin: 0 auto;
 }
 .line-1 {
 width: 1px;
 height: 6em;
 background: grey;
 top: 8.6em;
 left: 0;
 right: 0;
 margin: 0 auto;
 }
 .balloon-2 {
 background: blue;
 width: 6em;
 height: 7.4em;
 left: 10em;
 top: 24em;
 border-radius: 50%;
 z-index: 0;
 }
 .inner-balloon-2 {
 background: white;
 opacity: 0.3;
 width: 5em;
 height: 6.4em;
 left: 0.1em;
 top: 0.2em;
 border-radius: 50%;
 }
 .knot-2 {
 background: blue;
 clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
 width: 1em;
 height: 1em;
 top: 7.2em;
 left: 0;
 right: 0;
 margin: 0 auto;
 }
 .line-2 {
 width: 1px;
 height: 6em;
 background: grey;
 top: 8.2em;
 left: 0;
 right: 0;
 margin: 0 auto;
 }
 .balloon-3 {
 background: yellow;
 width: 6.6em;
 height: 8em;
 left: 17em;
 top: 24em;
 border-radius: 50%;
 z-index: 0;
 }
 .inner-balloon-3 {
 background: white;
 opacity: 0.3;
 width: 5.6em;
 height: 7em;
 left: 0em;
 top: 0em;
 border-radius: 50%;
 }
 .knot-3 {
 background: yellow;
 clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
 width: 1em;
 height: 1em;
 top: 7.6em;
 left: 0;
 right: 0;
 margin: 0 auto;
 }
 .line-3 {
 width: 1px;
 height: 6em;
 background: grey;
 top: 8.6em;
 left: 0;
 right: 0;
 margin: 0 auto;
 }
 .container:hover>.balloon-1, .container:focus>.balloon-1 {
 animation: up 3s ease-in infinite;
 }
 .container:hover>.balloon-2, .container:focus>.balloon-2 {
 animation: up 3s 300ms ease-in infinite;
 }
 .container:hover>.balloon-3, .container:focus>.balloon-3 {
 animation: up 3s -100ms ease-in infinite;
 }
 @keyframes up {
 to {
 top: -14em;
 }
 }
完整代码+码上掘金
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 张坤的博客!
 评论