Topic 13 of 30
Animations
Overview
CSS animations (@keyframes) allow multi-step animations that run automatically without JavaScript. They are ideal for loading spinners, attention-grabbing effects, skeleton loaders, and entrance animations.
Syntax
css
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-in {
animation: fadeInUp 0.6s ease forwards;
animation-delay: 0.2s;
}
/* Properties */
animation-name: fadeInUp;
animation-duration: 0.6s;
animation-timing-function: ease;
animation-delay: 0.2s;
animation-iteration-count: infinite; /* or number */
animation-direction: alternate;
animation-fill-mode: forwards; /* keeps end state */Common Pitfalls
- animation-fill-mode: forwards keeps the element in its final state — without it, the element snaps back.
- Use will-change: transform, opacity to hint the browser to GPU-accelerate the animation.
- Interview tip: Prefer animating transform and opacity — they don't cause layout reflow. Avoid animating width, height, margin.
Real-World Example
A skeleton loading animation and entrance animation for a dashboard:
example
css
/* Skeleton loader shimmer */
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(
90deg,
#1a1a1a 25%,
#2a2a2a 50%,
#1a1a1a 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 8px;
}
/* Pulsing notification badge */
@keyframes pulse-ring {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(1.8); opacity: 0; }
}
.notification-dot::after {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
background: #FFD700;
animation: pulse-ring 1.5s ease-out infinite;
}