How to Create CSS Easing Curves and Animations
Easing curves control how animations accelerate and decelerate. The difference between a cheap-feeling animation and a polished one is almost always the easing โ linear motion feels robotic, while a well-chosen curve feels natural and intentional. CSS gives you full control over easing with cubic-bezier().
- Master CSS transitions and animations with custom easing curves.
- Covers built-in easing keywords.
- Covers custom easing with cubic-bezier().
- Covers common custom curves.
- Covers keyframe animations with easing.
Built-In Easing Keywords
CSS provides five easing keywords: ease (default โ starts fast, decelerates), linear (constant speed โ mechanical feel), ease-in (starts slow, accelerates โ good for exits), ease-out (starts fast, decelerates โ good for entrances), ease-in-out (slow start and end โ good for continuous motion). ease-out is the most universally useful โ elements appear to arrive at their destination naturally, like a ball rolling to a stop.
Custom Easing with cubic-bezier()
cubic-bezier() defines a custom easing curve with four control points:
transform and opacity for smooth 60fps performance. These properties are handled by the GPU compositor and skip expensive layout recalculations.transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
The four values are x1, y1, x2, y2 โ the positions of two control handles on a timing curve. x values must be between 0 and 1; y values can exceed this range for bounce or overshoot effects. The Easing Wizard lets you drag control points visually and see the resulting motion in real time.
Common Custom Curves
Material Design standard: cubic-bezier(0.4, 0, 0.2, 1) โ a refined ease-out used across Google products. Overshoot/bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55) โ elements overshoot their target and snap back. Snappy entrance: cubic-bezier(0, 0.55, 0.45, 1) โ fast start with a smooth landing. Apple-style spring: cubic-bezier(0.25, 0.1, 0.25, 1) โ subtle, elegant deceleration.
width, height, top, or left. These trigger layout recalculations on every frame and can drop performance below 60fps.Keyframe Animations with Easing
For complex multi-step animations, use @keyframes with animation-timing-function:
@keyframes slideIn {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.element {
animation: slideIn 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
The easing applies to the entire animation. For different easing at different stages, set animation-timing-function within individual keyframe blocks.
Animation Performance
Animate only transform and opacity โ these properties are GPU-accelerated and don't trigger layout recalculation. Animating width, height, margin, padding, top, or left forces the browser to recalculate layout on every frame, causing jank. If you need to animate size, use transform: scale() instead of width/height. Always respect prefers-reduced-motion by wrapping animations in @media (prefers-reduced-motion: no-preference).