CSS Advanced
CSS Animations
Animations let elements change over time on their own, without hover or interaction. You define stages with a @keyframes rule, then attach it to an element with the animation properties to control timing, repetition, and direction.
Defining @keyframes
A @keyframes rule lists the states an animation passes through, either with from/to or percentage stops. You then reference it by name in the animation property.
@keyframes slide {
from { transform: translateX(0); }
to { transform: translateX(200px); }
}
.box { animation: slide 2s ease-in-out infinite alternate; }The animation properties
| Property | Purpose |
|---|---|
| animation-name | Which @keyframes to run |
| animation-duration | How long one cycle lasts |
| animation-timing-function | Speed curve within each cycle |
| animation-delay | Wait before starting |
| animation-iteration-count | How many times (or infinite) |
| animation-direction | normal, reverse, alternate |
| animation-fill-mode | Styles kept before/after running |
<!DOCTYPE html>
<html>
<head>
<style>
body { display:flex; gap:14px; justify-content:center; align-items:flex-end;
height:200px; background:#0f172a; }
.dot { width:20px; height:20px; border-radius:50%; background:#22d3ee;
animation: bounce 0.8s ease-in-out infinite; }
.dot:nth-child(2){ animation-delay: 0.15s; background:#818cf8; }
.dot:nth-child(3){ animation-delay: 0.3s; background:#f472b6; }
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-40px); }
}
</style>
</head>
<body>
<div class="dot"></div><div class="dot"></div><div class="dot"></div>
</body>
</html>Multi-step keyframes
Percentage stops let an animation move through many states in one cycle. You can animate several properties at each stop for rich effects like a pulsing, color-shifting badge.
<!DOCTYPE html>
<html>
<head>
<style>
body { display:grid; place-items:center; height:220px; background:#111827; font-family:sans-serif; }
.badge {
padding: 16px 30px; border-radius:999px; color:#fff; font-weight:bold;
animation: pulse 2.5s ease-in-out infinite;
}
@keyframes pulse {
0% { background:#ef4444; transform: scale(1); box-shadow:0 0 0 0 rgba(239,68,68,.6); }
50% { background:#8b5cf6; transform: scale(1.12); box-shadow:0 0 0 18px rgba(139,92,246,0); }
100% { background:#ef4444; transform: scale(1); box-shadow:0 0 0 0 rgba(239,68,68,0); }
}
</style>
</head>
<body>
<div class="badge">LIVE</div>
</body>
</html>A spinning loader
Combining an infinite linear rotation with a partially transparent border is the classic way to build a pure-CSS spinner.
<!DOCTYPE html>
<html>
<head>
<style>
body { display:grid; place-items:center; height:200px; background:#020617; }
.spinner {
width:70px; height:70px; border-radius:50%;
border:8px solid rgba(255,255,255,.15);
border-top-color:#22d3ee;
animation: rotate 0.9s linear infinite;
}
@keyframes rotate { to { transform: rotate(360deg); } }
</style>
</head>
<body>
<div class="spinner"></div>
</body>
</html>Use animation-fill-mode: forwards to keep the final keyframe styles after a non-repeating animation ends, instead of snapping back to the start.
Respect users who prefer reduced motion by wrapping heavy animation in a @media (prefers-reduced-motion: no-preference) query.
Key points
- @keyframes defines the stages of an animation by name.
- animation attaches the keyframes and controls timing and repetition.
- Percentage stops allow many states in one cycle.
- infinite plus alternate makes a smooth back-and-forth loop.
- fill-mode: forwards keeps the end state after the animation finishes.
