要查看下方框中的动画,请点击“播放动画”复选框或将光标悬停在框上。当动画激活时,顶部的云会改变形状,雪花会落下,底部的雪层会升高。要暂停动画,请取消选中复选框或将光标从框上移开。
<!-- See aria-label: https://mdn.org.cn/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label -->
<input
type="checkbox"
id="animate"
aria-label="Toggle the play state of the animation" />
<label for="animate">the animation</label>
<div class="root">
<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i
><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i
><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i
><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i
><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
<div class="cloud"></div>
<div class="ground"></div>
</div>
i {
display: inline-block;
height: 16px;
width: 16px;
border-radius: 50%;
animation: falling 3s linear 0s infinite backwards;
/* Snowflakes are made with CSS linear gradients (https://mdn.org.cn/en-US/docs/Web/CSS/CSS_Images/Using_CSS_gradients) */
background-image:
linear-gradient(180deg, transparent 40%, white 40% 60%, transparent 60%),
linear-gradient(90deg, transparent 40%, white 40% 60%, transparent 60%),
linear-gradient(45deg, transparent 43%, white 43% 57%, transparent 57%),
linear-gradient(135deg, transparent 43%, white 43% 57%, transparent 57%);
}
i:nth-of-type(4n) {
/* Using tree structural pseudo-classes to create randomness - https://mdn.org.cn/en-US/docs/Web/CSS/:nth-of-type */
height: 30px;
width: 30px;
transform-origin: right -30px;
}
i:nth-of-type(4n + 1) {
height: 24px;
width: 24px;
transform-origin: left 30px;
}
i:nth-of-type(4n + 2) {
height: 10px;
width: 10px;
transform-origin: -30px 0;
}
i:nth-of-type(4n + 3) {
height: 40px;
width: 40px;
transform-origin: -50px 0;
}
i:nth-of-type(4n) {
animation-duration: 5.3s;
animation-iteration-count: 12;
transform-origin: -10px -20px;
}
i:nth-of-type(4n + 1) {
animation-duration: 3.1s;
animation-iteration-count: 20;
transform-origin: 10px -20px;
}
i:nth-of-type(4n + 2) {
animation-duration: 1.7s;
animation-iteration-count: 35;
transform-origin: right -20px;
}
i:nth-of-type(3n) {
animation-delay: 2.3s;
}
i:nth-of-type(3n + 1) {
animation-delay: 1.5s;
}
i:nth-of-type(3n + 2) {
animation-delay: 3.4s;
}
i:nth-of-type(5n) {
animation-timing-function: ease-in-out;
}
i:nth-of-type(5n + 1) {
animation-timing-function: ease-out;
}
i:nth-of-type(5n + 2) {
animation-timing-function: ease;
}
i:nth-of-type(5n + 3) {
animation-timing-function: ease-in;
}
i:nth-of-type(5n + 4) {
animation-timing-function: linear;
}
i:nth-of-type(11n) {
animation-timing-function: cubic-bezier(0.2, 0.3, 0.8, 0.9);
}
i:nth-of-type(7n) {
opacity: 0.5;
}
i:nth-of-type(7n + 2) {
opacity: 0.3;
}
i:nth-of-type(7n + 4) {
opacity: 0.7;
}
i:nth-of-type(7n + 6) {
opacity: 0.6;
animation-timing-function: ease-in;
transform-origin: left 10px;
}
i:nth-of-type(7n + 1) {
opacity: 0.8;
}
.root {
height: 580px;
background-color: skyblue;
border: 1px solid darkgrey;
position: relative;
overflow: hidden;
}
.ground,
.cloud {
position: absolute;
top: 0;
right: 0;
left: 0;
background-repeat: no-repeat;
}
.cloud {
width: 100%;
height: 150px;
background: white;
border-radius: 0 0 90px 33% / 0 0 45px 50px;
box-shadow:
5px 15px 15px white,
-5px 15px 15px white,
0 20px 20px rgb(125 125 125 / 0.5);
animation:
clouds ease 5s alternate infinite 0.2s,
wind ease-out 4s alternate infinite;
}
.ground {
bottom: 0;
background-image: linear-gradient(to top, white 97%, 99%, #bbbbbb 100%);
background-position: center 580px;
animation: snowfall linear 300s forwards;
border: 1px solid grey;
/* Put the ground into a 3D rendering context (because the snow flakes are in a 3d rendering context) */
transform: translate3d(0, 0, 0);
}
@keyframes snowfall {
from {
background-position: center 580px;
}
to {
background-position: center 280px;
}
}
@keyframes clouds {
from {
border-radius: 0 0 90px 33% / 0 0 45px 50px;
}
to {
border-radius: 0 0 40px 50% / 0 0 55px 80px;
}
}
@keyframes wind {
from {
height: 150px;
}
to {
height: 100px;
}
}
@keyframes falling {
from {
transform: translate(0, -50px) rotate(0deg) scale(0.9, 0.9);
}
to {
transform: translate(30px, 600px) rotate(360deg) scale(1.1, 1.1);
}
}
/* By default, the animations are paused. */
i,
div[class] {
animation-play-state: paused;
}
/* When the div is hovered, the animation plays. Also,
when the input is checked, the animation coming after the checked checkbox plays */
div:hover *,
input:checked ~ div * {
animation-play-state: running;
}
/* Change the content of the label that comes right after the input. Included aria-label on the label to improve accessibility. */
input + label::before {
content: "Play ";
}
input:checked + label::before {
content: "Pause ";
}
此示例动画使用 animation-iteration-count 使雪花重复落下,使用 animation-direction 使云来回移动,使用 animation-fill-mode 使雪层随着云的移动而升高,并使用 animation-play-state 暂停动画。
点击上方示例中的“播放”按钮,可以在 MDN Playground 中查看或编辑动画代码。
CSS 动画模块第 2 级还引入了 animation-trigger、animation-trigger-exit-range、animation-trigger-exit-range-end、animation-trigger-exit-range-start、animation-trigger-range、animation-trigger-range-end、animation-trigger-range-start、animation-trigger-timeline 和 animation-trigger-type 属性。目前,没有浏览器支持这些功能。