Recommended Easing Values for Professional UI Animations: A Practical Guide
Strong custom cubic-bezier curves (0.23, 1, 0.32, 1), (0.77, 0, 0.175, 1), and (0.32, 0.72, 0, 1) should replace default CSS easings like ease, ease-in, and ease-out to achieve crisp, responsive motion in professional interfaces.
The emilkowalski/skills repository treats easing as a core design-engineering decision, not an afterthought. According to the standards codified in skills/review-animations/STANDARDS.md, default CSS easings are deliberately too soft for deliberate, professional motion. This article breaks down the exact recommended easing values for professional UI animations and how to implement them.
Why Default CSS Easings Fall Short
Default browser easings create sluggish, uninspired motion. The repository's skills/animate/SKILL.md explicitly warns that built-in CSS easings are "too weak" for modern product interfaces.
Avoid these defaults:
| Easing | Problem |
|---|---|
ease-in |
Never use on UI — delays the visible response, making interactions feel broken |
ease |
Too soft for most transitions; acceptable only for subtle hover feedback |
ease-out |
Browser default lacks the aggressive start needed for responsive feel |
ease-in-out |
Default creates awkward pacing for longer movements |
The skills/improve-animations/AUDIT.md flags any occurrence of ease-in as a mandatory replacement finding.
Core Cubic-Bezier Tokens from the Standards
The skills/review-animations/STANDARDS.md file defines three production-ready CSS custom properties. These are the recommended easing values for professional UI animations:
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* crisp entrance/exit */
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* on-screen movement */
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* iOS-style panels */
}
What Makes These Values Work
-
--ease-out(0.23, 1, 0.32, 1): The first control point(0.23, 1)forces rapid initial velocity. This creates the "fast-start" feel that makes interfaces feel responsive and snappy. -
--ease-in-out(0.77, 0, 0.175, 1): The asymmetric curve(0.77, 0)generates strong acceleration and deceleration. This pattern feels natural for elements traveling significant distance across the screen. -
--ease-drawer(0.32, 0.72, 0, 1): Matches iOS system motion. The(0.32, 0.72)initial pull creates that familiar, buttery resistance before the smooth settle.
Situational Easing Selection
The repository provides a decision order for applying these tokens:
| Situation | Easing Choice | Rationale |
|---|---|---|
| Enter / exit animations | var(--ease-out) |
Fast start feels responsive; soft finish avoids jarring landings |
| On-screen movement / morphing | var(--ease-in-out) |
Acceleration and deceleration for longer travels |
| Hover / color changes | ease |
Subtle, non-intrusive feedback |
| Constant motion (marquees, progress bars) | linear |
Uniform speed matches user expectation |
| Side panels / modals | var(--ease-drawer) |
Familiar iOS-style motion language |
Practical Implementation Examples
CSS-Only Transitions
Define tokens globally, then reference via var():
/* Global definition */
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}
/* Button press feedback — 160ms keeps it under the 300ms ceiling */
button {
transition: transform 160ms var(--ease-out);
}
button:active {
transform: scale(0.97);
}
/* Card entrance animation */
.card-enter {
animation: slide-up 250ms var(--ease-out) forwards;
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Web Animations API (JavaScript)
// Drawer slide-in using the iOS-style curve
const drawer = document.querySelector('.drawer');
drawer.animate(
[
{ transform: 'translateX(-100%)' },
{ transform: 'translateX(0)' }
],
{
duration: 250,
easing: 'cubic-bezier(0.32, 0.72, 0, 1)' // --ease-drawer
}
);
// Modal scale-in with strong ease-out
dialog.animate(
[
{ opacity: 0, transform: 'scale(0.96)' },
{ opacity: 1, transform: 'scale(1)' }
],
{
duration: 200,
easing: 'cubic-bezier(0.23, 1, 0.32, 1)' // --ease-out
}
);
Reduced Motion Support
The standards require respecting prefers-reduced-motion. Keep timing consistent but eliminate transform-heavy motion:
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
Sourcing Additional Curves
For specialized motion needs, skills/emil-design-eng/SKILL.md recommends curated libraries over hand-rolling:
- easing.dev — Mathematical exploration of easing functions with visual previews
- easings.co — Production-ready CSS cubic-bezier values with copy-paste convenience
These collections maintain the same rigor as the repository's internal standards.
Implementation Checklist
- Declare tokens once in a global
:rootselector - Reference via
var()throughout component styles and animation APIs - Audit and replace any
ease-inusage with appropriate custom curves - Cap durations at 300ms per the repository's ceiling guideline
- Honor reduced-motion with timing-only fallbacks
Summary
- Primary recommended easing values for professional UI animations:
cubic-bezier(0.23, 1, 0.32, 1),cubic-bezier(0.77, 0, 0.175, 1), andcubic-bezier(0.32, 0.72, 0, 1) - Never use
ease-inon UI elements — it delays visible response - Default CSS easings are too soft — replace with strong custom curves
- Keep all animations under 300ms for crisp, professional feel
- Source additional curves from easing.dev or easings.co rather than inventing values
Frequently Asked Questions
What is the best easing for button click feedback?
Use cubic-bezier(0.23, 1, 0.32, 1) (--ease-out) with a short duration of 120-160ms. This creates immediate visual response on press with a soft settle, confirming the interaction without delay.
Why should I avoid ease-in completely in UI animations?
ease-in starts slow and accelerates, which delays the moment the user sees motion begin. According to skills/review-animations/STANDARDS.md, this makes interactions feel sluggish and unresponsive. The repository flags any ease-in usage as a mandatory replacement finding.
How do I choose between --ease-out and --ease-in-out?
Use --ease-out (0.23, 1, 0.32, 1) for elements entering or leaving the viewport — the fast start delivers responsiveness. Use --ease-in-out (0.77, 0, 0.175, 1) for elements moving between visible positions, where the acceleration/deceleration pattern feels more natural for longer travel distances.
What duration should I pair with these easing curves?
The repository recommends keeping all UI animations under 300ms. Pair --ease-out with 160-250ms for entrances, --ease-drawer with 250-300ms for panel slides, and reserve shorter 120-200ms durations for hover states and micro-interactions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →