Why Ease-In Should Never Be Used for UI Interactions: Lessons from the emilkowalski/skills Repository
Ease-in should never be used for UI interactions because it starts slow and delays the exact moment the user is watching, making interfaces feel sluggish and unresponsive compared to ease-out alternatives.
In the emilkowalski/skills repository, the author establishes strict animation standards that explicitly classify ease-in as a "finding"—a code smell that must be corrected during review. This open-source collection of design engineering skills documents why perceptual speed matters more than actual duration, and how the right easing curves can make a 200ms animation feel instantaneous while the wrong ones make it feel like lag.
The Problem with Ease-In in User Interfaces
According to skills/improve-animations/AUDIT.md (line 28), the repository explicitly states: "ease-in on UI is always a finding—it starts slow, delaying the exact moment the user is watching." This architectural decision stems from a fundamental mismatch between the curve's mathematical behavior and user expectations.
When a user clicks a button or triggers a dropdown, they expect immediate visual feedback. An ease-in curve accelerates from zero velocity, meaning the animation remains nearly invisible for the first 30-40% of its duration. This creates a perceptual delay that makes the interface feel broken or underpowered, even when the total animation time is identical to faster-feeling alternatives.
Perceptual Speed and User Expectations
The repository emphasizes that perceptual speed trumps actual duration. As documented in skills/review-animations/STANDARDS.md (line 27), a 200ms ease-out transition feels significantly faster than a 200ms ease-in because the motion begins immediately at maximum velocity.
This phenomenon occurs because:
- Ease-out provides instant feedback that the system registered the interaction
- Ease-in forces the user to wait through "dead time" before meaningful motion occurs
- Users unconsciously judge responsiveness by the time to first visible movement, not total animation time
Recommended Alternatives: Ease-Out and Custom Curves
The emilkowalski/skills codebase standardizes on ease-out for all entering and exiting animations, with specific cubic-bezier values defined as reusable CSS tokens.
CSS Token Definitions
In skills/review-animations/STANDARDS.md (lines 32-33), the repository defines global easing tokens that embody the "strong ease-out" philosophy:
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* strong ease-out for UI */
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* movement across screen */
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* specific for drawers */
}
These tokens ensure consistency across components while enforcing the "no ease-in" rule. New components must reference --ease-out rather than generic CSS keywords.
Button Interactions
For button press feedback, the standards recommend a subtle scale-down with a fast ease-out transition to confirm the interaction without delay. From STANDARDS.md (line 59):
button:active {
transform: scale(0.97);
transition: transform 160ms var(--ease-out); /* 160ms feels snappy */
}
This pattern provides immediate tactile feedback, whereas an ease-in curve would make the button feel unresponsive during the critical first 50ms of the press.
Dropdown Animations
Dropdowns represent the most common violation of this principle. As noted in skills/emil-design-eng/SKILL.md (line 46), "ease-in on dropdown … feels sluggish; ease-out gives instant feedback." The corrected implementation from skills/improve-animations/PLAN-TEMPLATE.md (line 32) shows:
.dropdown {
transition: transform 200ms var(--ease-out),
opacity 200ms var(--ease-out);
}
This ensures the menu appears to spring open immediately upon user action, rather than slowly gathering speed while the user waits.
Code Review Standards
The repository treats animation auditing as a first-class quality gate. The skills/improve-animations/AUDIT.md file mandates that reviewers flag any UI component using ease-in and replace it with ease-out or a custom cubic-bezier.
Key guidelines from STANDARDS.md (lines 21-24) specify:
- Entering or exiting →
ease-out(starts fast, feels responsive) - Hover / color change →
ease(standard CSS ease) - Never →
ease-infor any user-triggered interaction
Toast notifications follow the same pattern, using --ease-out for a smooth, quick entry over 400ms (STANDARDS.md, line 83), ensuring error messages and confirmations appear instantly when the user needs them most.
Summary
- Ease-in delays feedback by starting at zero velocity, breaking user expectations for immediate response.
- Ease-out feels faster than ease-in at identical durations because it provides instant initial movement.
- The
emilkowalski/skillsrepository defines CSS custom properties like--ease-out: cubic-bezier(0.23, 1, 0.32, 1)to standardize strong ease-out curves. - Code reviews explicitly flag ease-in on UI as a "finding" that must be replaced with ease-out or custom cubic-bezier curves.
- Buttons, dropdowns, and toasts should all use ease-out to maintain a consistent, responsive UI language.
Frequently Asked Questions
What makes ease-in feel slower than ease-out if they have the same duration?
Ease-in starts with zero velocity and accelerates, meaning the first half of the animation shows minimal visible change. Ease-out starts at maximum velocity and decelerates, so the user sees immediate displacement. As documented in the repository, users judge speed by time-to-first-movement, not total animation time, making ease-out feel responsive while ease-in feels delayed.
When is it acceptable to use ease-in according to the emilkowalski/skills standards?
The repository treats ease-in as "always a finding" for UI interactions. However, ease-in-out (cubic-bezier(0.77, 0, 0.175, 1)) is acceptable for elements that travel long distances across the screen, as the initial ease-out provides feedback while the final ease-in prevents jarring stops. Pure ease-in should never appear in user-facing components.
How do I migrate existing CSS from ease-in to the recommended patterns?
Replace transition-timing-function: ease-in with var(--ease-out) or cubic-bezier(0.23, 1, 0.32, 1). For enter animations, ensure you use the --ease-out token defined in STANDARDS.md. For micro-interactions like button presses, target 160ms duration with the strong ease-out curve to maintain consistency with the repository's design system.
Does ease-in ever make sense for non-UI animations?
The repository focuses specifically on UI interactions where user expectation demands immediate feedback. While the standards don't explicitly address cinematic or decorative animations, the underlying principle remains: any animation where a user is waiting for completion should avoid ease-in to prevent perceived lag. Ease-in might suit objects falling under gravity in game physics, but not interface elements responding to clicks or hovers.
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 →