When to Use Ease-Out vs Ease-In for UI Animations: A Design Engineering Guide

Use ease-out for all entering, exiting, and interactive UI animations to provide immediate visual feedback, reserve ease-in strictly for elements that travel across the screen, and never apply ease-in to direct user interactions like button presses or hover states.

Choosing the correct CSS timing function determines whether your interface feels responsive or sluggish to users. The emilkowalski/skills repository codifies specific rules for when to use ease-out versus ease-in, establishing that this distinction directly impacts perceived performance and user satisfaction rather than serving as a purely aesthetic choice.

Ease-Out: The Default for Entering and Exiting UI

According to skills/review-animations/STANDARDS.md, ease-out should serve as the default timing function for all entering and exiting animations, including dropdown menus opening, modals appearing, and tooltips fading in. This curve starts quickly—providing immediate visual confirmation that a user action registered—then decelerates as the element settles into its final position.

The repository emphasizes that this snappy start matches human expectations for interface responsiveness. When a user clicks a button or toggles a menu, the resulting motion must begin instantly to create the illusion of direct manipulation.

Why Ease-In Feels Sluggish on Interactive Elements

The skills/emil-design-eng/SKILL.md file provides concrete comparisons demonstrating that ease-in applied to a dropdown menu feels significantly slower than ease-out at the exact same duration. Because ease-in delays the start of movement, users experience a perceptible lag during the exact moment they are watching the interface for confirmation. This creates the sensation of a sluggish or unresponsive application, even if the total animation time is only 200 milliseconds.

When to Use Ease-In: Motion and Travel

Reserve ease-in exclusively for moving or morphing elements that travel significant distances across the screen, such as panels sliding in from the side or large sections transitioning into view. As documented in skills/review-animations/STANDARDS.md, these animations should mimic natural physics by starting slowly, accelerating, and then decelerating.

Unlike UI feedback elements, objects entering from outside the viewport benefit from the acceleration phase. A sliding panel that starts at full speed feels unnatural and jarring; the gradual buildup of speed creates a sense of mass and momentum. For these scenarios, the repository specifically recommends using ease-in-out rather than pure ease-in to ensure the deceleration phase is equally smooth and controlled.

Critical Anti-Pattern: Never Use Ease-In on Direct UI Feedback

The skills/review-animations/SKILL.md file contains an explicit rule: "Never ease-in on UI". This prohibition covers button press feedback, hover state transitions, and any direct manipulation interface. The skills/improve-animations/AUDIT.md checklist formalizes this by flagging any instance of ease-in applied to UI elements as a critical finding that must be corrected during code review.

Applying ease-in to a button's :active state or a hover effect violates the principle of immediate feedback. The user expects to see the result of their action the instant their finger touches the glass or their cursor clicks the mouse; any delay in the start of motion breaks this illusion and degrades the user experience.

Implementing Custom Easing Tokens

Rather than relying on generic CSS keywords, the repository advocates defining strong custom cubic-bezier curves as design tokens. This approach ensures consistency across the codebase and makes animation intent explicit for future maintainers.

Define reusable easing tokens in your CSS:

/* src/styles/tokens.css – shared easing variables */
--ease-out:    cubic-bezier(0.23, 1, 0.32, 1);   /* strong UI ease-out */
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* smooth travel */

By centralizing these definitions, you prevent arbitrary values from proliferating and ensure that every animation follows the established standards for responsiveness.

Practical Code Examples

Entering and Exiting Animations with Ease-Out

Apply the --ease-out token to all direct user feedback and element entry animations:

/* Button press feedback */
.button:active {
  transform: scale(0.97);
  transition: transform 160ms var(--ease-out);
}

/* Dropdown opening */
.dropdown {
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 200ms var(--ease-out),
    transform 200ms var(--ease-out);
}
.dropdown.open {
  opacity: 1;
  transform: translateY(0);
}

Sliding Panels with Ease-In-Out

Use --ease-in-out for elements that travel across the viewport:

/* Sliding panel */
.panel {
  transform: translateX(-100%);
  transition: transform 300ms var(--ease-in-out);
}
.panel.visible {
  transform: translateX(0);
}

Enforcing Standards with Lint Rules

The skills/improve-animations/AUDIT.md guidelines suggest automating the detection of anti-patterns. A custom lint rule can catch disallowed usage before it reaches production:

// Example lint rule (pseudo-code) – catches disallowed usage
if (property === 'transition' && value.includes('ease-in')) {
  report('Never use ease-in on UI elements; use --ease-out instead.');
}

Summary

  • Use ease-out as the default for all entering, exiting, and interactive UI animations to provide immediate visual feedback.
  • Reserve ease-in strictly for elements traveling across the screen, and prefer ease-in-out over pure ease-in for these cases.
  • Never apply ease-in to direct user feedback such as button presses, hover states, or toggle switches.
  • Define custom cubic-bezier tokens (e.g., --ease-out: cubic-bezier(0.23, 1, 0.32, 1)) to enforce consistency across your codebase.
  • Audit existing code using the checklist in skills/improve-animations/AUDIT.md to identify and refactor incorrect easing usage.

Frequently Asked Questions

Why does ease-in feel slower than ease-out even at the same duration?

ease-in delays the start of movement by beginning slowly and accelerating, creating a perceptual lag during the critical first milliseconds when the user is watching for feedback. In contrast, ease-out spends most of its time in the initial fast phase, making the interface feel immediately responsive even when the total animation time is identical.

Can I use ease-in-out instead of ease-out for UI feedback?

While ease-in-out is acceptable for elements traveling across the screen, the skills/review-animations/STANDARDS.md documentation recommends using a strong ease-out curve (such as cubic-bezier(0.23, 1, 0.32, 1)) for direct UI feedback. Pure ease-out maximizes the snappiness of the initial response, whereas ease-in-out still wastes precious milliseconds on the acceleration phase that users interpret as delay.

What cubic-bezier values should I use for custom easing curves?

According to the standards in skills/review-animations/STANDARDS.md, use cubic-bezier(0.23, 1, 0.32, 1) for a strong UI ease-out that feels snappy yet smooth, and cubic-bezier(0.77, 0, 0.175, 1) for ease-in-out on traveling elements. These specific values provide the proper deceleration and acceleration characteristics that match human perceptual expectations.

How do I audit existing code for incorrect ease-in usage?

Reference the checklist provided in skills/improve-animations/AUDIT.md, which explicitly flags any ease-in usage on UI elements as a finding requiring correction. Implement automated linting rules to catch ease-in in transition properties, and manually review animations for button states, hover effects, and dropdowns to ensure they use the defined --ease-out token instead.

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 →