To make CSS animations feel more natural, match the easing curve to the motion’s purpose, keep transitions explicit, and honor the user’s reduced-motion preference. Use ease-out for an element settling into place, ease-in for one gathering speed as it leaves, linear for constant-speed motion, and a custom cubic-bezier() curve only when a preset does not fit.
Choose easing by the motion’s purpose
Easing controls how a value changes over time, shaping the perceived acceleration and deceleration of an animation. MDN explains that easing functions control the transformation of values and can help motion resemble physical objects: MDN: easing functions.
First decide what the motion communicates: arrival, departure, emphasis, progress, or a physical metaphor. Then choose a curve that supports that impression rather than applying the same timing to every element.
| Timing function | Perceived motion | Good fit |
|---|---|---|
linear |
Moves at a constant rate | Constant-speed loops, such as a progress indicator |
ease |
Starts and ends more gently, with faster movement between | A general-purpose transition when no more specific behavior is needed |
ease-in |
Starts slowly, then accelerates | An element gathering speed before it leaves |
ease-out |
Starts quickly, then slows | An element arriving and settling into place |
ease-in-out |
Starts and ends gently, speeding up in the middle | A complete departure-and-arrival cycle |
steps() |
Changes in discrete jumps rather than continuously | Sprite-like or segmented movement |
MDN notes that gradually increasing an element’s speed can suggest it is gathering momentum: MDN: animation-timing-function. That impression is useful for departure or buildup, but it may feel wrong for a control that should respond immediately.
#1 Best Overall
Use cubic-bezier() when presets do not fit
cubic-bezier() defines a custom timing curve when the built-in keywords do not express the intended motion. Its four values describe two control points; the first and third values must fall between 0 and 1, while the second and fourth can extend beyond that range. Values beyond the usual range can create overshoot, so use them only when a deliberate elastic effect supports the design.
.drawer {
transition: transform 320ms cubic-bezier(.22, .8, .26, 1);
}
This curve is a custom example, not a universal recipe. Adjust the control points to shape how quickly the drawer starts, how it decelerates, and whether it settles without overshooting. A preset keyword is easier for another developer to understand; document a custom curve so its purpose remains clear.
Rank #2
Make transitions explicit and responsive
A transition is usually the simpler option when a property changes between two states. Keyframes are more appropriate when the motion needs several stages. For transitions, name the properties, duration, and timing function instead of using all; explicit declarations make it easier to maintain and debug which changes animate. The CSS Transitions specification describes how transition properties control this behavior: W3C: CSS Transitions.
.button {
transition: transform 180ms ease-out, background-color 140ms ease-out;
}
.button:hover,
.button:focus-visible {
transform: translateY(-2px);
}
These durations are illustrative values, not fixed rules. Tune duration to the distance and importance of the change: a small hover response should feel prompt, while a larger panel movement may need more time for the spatial relationship to remain legible.
Free tools Windows power users keep installed
One-click scans. No signup required.
Check the result with a keyboard as well as a pointer. In particular, test the focus-visible state, what happens if the state changes before a transition finishes, and whether repeated triggering feels controlled. A transition should not obscure the control’s state or make interaction feel delayed.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Respect prefers-reduced-motion
Some users ask their operating system or browser to reduce motion. The prefers-reduced-motion media feature lets a page respond to that preference. W3C Technique C39 describes the objective as allowing users to prevent animations, including motion animations, from being displayed on web pages: W3C Technique C39. MDN documents the media feature and its values: MDN: prefers-reduced-motion.
Rank #4
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
This broad override suppresses most animation and transition effects, but it is not a substitute for checking the page’s specific motion. For non-essential animation, consider replacing movement with a less motion-heavy state change. For animation that continues automatically and is not essential, provide a way to pause or turn it off when appropriate; W3C notes that the ability to turn off non-essential animations is a site-wide setting: W3C Technique G186.
Quick Recap
Best Value
A practical tuning sequence
- Identify the message. Decide whether the element is arriving, leaving, emphasizing something, showing progress, or representing a physical action.
- Pick a matching curve. Start with an easing keyword or
linearfor constant speed; usesteps()for discrete changes. - Adjust duration to distance and importance. Keep small interactions responsive and give larger movements enough time to follow.
- Use a custom curve only for a reason. Try
cubic-bezier()if a preset does not produce the intended acceleration or settling, and keep any overshoot purposeful. - Name transition properties explicitly. Avoid an unspecified
alltransition so the behavior stays understandable. - Test interaction and accessibility. Try pointer and keyboard states, interrupted and repeated triggers, and the reduced-motion variant.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

