Animation
Animation Property
animation-name.animation-duration.animation-timing-function:<easing-function>.animation-delay: 支持负值.animation-iteration-count:infinite | <number>执行次数.- 支持
0与小数. - 不支持负值.
animation-direction:normal:0%->100%方向.reverse:100%->0%方向.alternate/alternate-reverse: 不断交替方向.
animation-fill-mode:forwards/backwards/both.animation-play-state:paused/running.
@media only screen and (prefers-reduced-motion: reduce) {
.element {
animation: none;
}
}
Animation Fill Mode
forwards: 动画结束后, 应用动画最后一帧属性值.backwards: 动画开始前, 应用动画第一帧属性值.both: 同时应用上述两种效果.
animation-direction | animation-iteration-count | last keyframe |
|---|---|---|
normal | even or odd | 100% |
reverse | even or odd | 0% |
alternate | even | 0% |
alternate | odd | 100% |
alternate-reverse | even | 100% |
alternate-reverse | odd | 0% |
normal/alternate | 0 | 0% |
reverse/alternate-reverse | 0 | 100% |
| animation-direction | first keyframe |
|---|---|
normal/alternate | 0% |
reverse/alternate-reverse | 100% |
Animation Play State
利用 animation-paly-state
与 JavaScript 添加 .animate 类控制动画开始和停止.
div {
animation-play-state: paused;
}
:checked ~ div {
animation-play-state: running;
}
@media only screen and (prefers-reduced-motion: reduce) {
.to-animate {
animation: none;
}
}
.to-animate {
animation: animationName 1.5s linear;
animation-iteration-count: infinite;
animation-play-state: paused;
}
.animate {
animation-play-state: running;
}
element.classList.add('animate')
setTimeout(() => element.classList.remove('animate'), duration)
Animation Timeline
Implement scroll-driven animation
with CSS animation-timeline:
scroll()timeline.view()timeline.
@media not (prefers-reduced-motion) {
footer::after {
position: fixed;
inset-inline-start: 0;
bottom: 0;
width: 100%;
height: 1em;
content: '';
transform-origin: top left;
animation: grow-progress linear;
animation-timeline: scroll();
}
@keyframes grow-progress {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
}
@media not (prefers-reduced-motion) {
img {
animation: slide-in;
animation-timeline: view();
animation-range: 0% 50%;
}
@keyframes slide-in {
0% {
opacity: 0;
transform: translateX(100%);
}
100% {
opacity: 1;
transform: translateX(0%);
}
}
}
Offset Animation
offset,
animating an element along a defined path:
.path {
/* Offset position */
offset: auto;
offset: 10px 30px;
offset: none;
/* Offset path */
/* stylelint-disable-next-line function-no-unknown */
offset: ray(45deg closest-side);
offset: url('arc.svg');
offset: path('M 100 100 L 300 100 L 200 300 z');
/* Offset path with distance and/or rotation */
offset: url('circle.svg') 100px;
offset: url('circle.svg') 40%;
offset: url('circle.svg') 30deg;
offset: url('circle.svg') 50px 20deg;
/* Including offset anchor */
/* stylelint-disable-next-line function-no-unknown */
offset: ray(45deg closest-side) / 40px 20px;
offset: url('arc.svg') 2cm / 0.5cm 3cm;
offset: url('arc.svg') 30deg / 50px 100px;
}
Animation Patterns
Animation FLIP Pattern
- First: 初始状态.
- Last: 动画结束状态.
- Invert: last 至 first 的
transform属性. - Play:
transition: transform .2s linear.
@media only screen and (prefers-reduced-motion: reduce) {
.scale-up {
transition: none;
}
}
/* first: scale(1), last: scale(1.2) */
.scale-up {
transform: scale(0.8);
transition: transform 0.2s linear;
}
.scale-up:hover,
.scale-up:focus {
transform: none;
}
Animation Bounce Cache Pattern
- First
-100. - Then
+5/+20. - Finally
0. - 切换动画时, 需要先把之前的动画清除: 防止出现闪烁 Bug.
Animation Helper
opacity.overflow: hidden.transform:scale/translate.transition.animation-delay.width/heightmax-width/max-height.margin.border-*.background.background-position.backgroundwith multiplegradient.- Single
box-shadow - Multiple
box-shadow. *-clip-*.mask-*.filter.backdrop-filter.- Pseudo element (
::before/::after). - Pseudo class (
:hover/:focus/:target). - Changing
top/right/bottom/leftof pseudo element can change animation start point: e.g.bottom: 0, right: 0changewidth/heightfrom0to100%, size animation will start frombottom-rightcorner.
.animation-container {
z-index: -1;
overflow: hidden;
}
/* 直接动画 */
.div {
animation-name: name;
animation-duration: 1s;
animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
animation-delay: 0.5s;
}
/* hover 后再播放动画, 高级化 transform + transition */
.div:hover,
.div:focus {
animation-name: name;
animation-duration: 1s;
animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
animation-delay: 0.5s;
}
Animation API
DOM events:
animationiteration: triggered after each animation iteration.animationend: triggered after an animation completes.animationstart: triggered at the start of an animation.
GreenSock Library
TweenMax
TweenMax.fromTo(element, 1, { x: 0 }, { x: 100 })
TimelineMax
const tl = new TimelineMax()
tl.staggerFrom(
[
'#Cap_1 > g > path:nth-child(1)',
'#Cap_1 > circle:nth-child(7)',
'#Cap_1 > path:nth-child(6)',
'#Cap_1 > circle:nth-child(5)',
],
1,
{
scaleY: 0,
scaleX: 0,
transformOrigin: 'center',
ease: Bounce.easeOut,
stagger: 0.2,
}
)
Animation References
- Animatable CSS properties.
- Animation 101 guide.
- Animation performance tier list.