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

  1. Declare tokens once in a global :root selector
  2. Reference via var() throughout component styles and animation APIs
  3. Audit and replace any ease-in usage with appropriate custom curves
  4. Cap durations at 300ms per the repository's ceiling guideline
  5. 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), and cubic-bezier(0.32, 0.72, 0, 1)
  • Never use ease-in on 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →