# Why Built‑In CSS Easing Curves Are Insufficient for Professional UI Animation

> Discover why generic CSS easing curves like ease in and ease out fall short for professional UI animation. Learn how to achieve precision and brand alignment for superior interfaces.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: deep-dive
- Published: 2026-08-06

---

**Built‑in CSS easing curves like `ease`, `ease‑in`, `ease‑out`, and `ease‑in‑out` are too generic for production UI work because they lack the precision, brand alignment, and performance characteristics that professional interfaces demand.**

The `emilkowalski/skills` repository explicitly rejects these native curves in favor of **strong custom cubic‑beziers** stored as design‑system tokens. According to the codebase's animation standards, native easings produce sluggish, inconsistent motion that breaks visual cohesion across browsers and components.

## The Core Problem: Native Curves Are Deliberately Generic

CSS ships with four basic easing functions intended for rapid prototyping, not polished products. In [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md), the maintainers state directly: *"Built‑in CSS easings are too weak. Use strong custom curves."*

These built‑in curves suffer from five critical limitations:

- **Fixed parameters** — The browser hardcodes values like `cubic-bezier(0.25, 0.1, 0.25, 1.0)` for `ease`, leaving no room for fine‑tuning acceleration to match brand personality
- **Low visual contrast** — Gentle slopes feel sluggish; subtle motion cues disappear during high‑frequency interactions
- **Browser variance** — Implementation differences between Safari and Chrome create divergent experiences
- **No token integration** — Impossible to enforce unified motion across large codebases without design‑system infrastructure
- **Single‑function symmetry** — Real UI often needs asymmetric curves (fast attack, slow decay) that native functions cannot express

## How the `skills` Repository Enforces Professional Motion

The codebase treats easing as a **first‑class design constraint** with explicit rules in multiple skill modules.

### The Audit Rule Against `ease‑in`

In [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md), the decision order for easing explicitly flags `ease‑in` as a finding. The rationale: *ease‑in "delays the moment the user is watching"* — creating perceived latency even when the animation technically starts immediately.

This audit rule enforces a user‑centric principle: **motion should feel responsive from frame one**, not build tension before revealing content.

### Custom Curves as Design Tokens

The [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md) module mandates that all easing values live as design‑system tokens. This ensures every component pulls from a vetted, consistent palette of motion curves.

Recommended external sources for production‑ready curves:

- [easing.dev](https://easing.dev/) — curated parametric easings
- [easings.co](https://easings.co/) — visual explorer with copy‑ready values

### Responsive Easing Guidelines

[`skills/review-animations/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/SKILL.md) emphasizes matching **component personality** to curve choice. A destructive action's exit animation demands different energy than a modal entrance — both impossible to achieve with the one‑size‑fits‑all `ease` keyword.

## Practical Implementation Patterns

### Token‑Based Easing in TypeScript

Store curves as design tokens with semantic names describing their motion character:

```typescript
// styles.ts — design-system tokens
export const easing = {
  enter: 'cubic-bezier(0.77, 0, 0.175, 1)',  // strong, decisive entrance
  exit:  'cubic-bezier(0.4, 0, 0.2, 1)',    // gentle, unobtrusive exit
  bounce: 'cubic-bezier(0.34, 1.56, 0.64, 1)', // playful overshoot
};

export const duration = {
  fast: '150ms',
  normal: '250ms',
  slow: '400ms',
};

```

Consume tokens in components for deterministic, brand‑aligned motion:

```tsx
// component.tsx
import { easing, duration } from './styles';

function SlideIn({ children }) {
  return (
    <div
      style={{
        animation: `slideUp ${duration.normal} ${easing.enter} both`,
      }}
    >
      {children}
    </div>
  );
}

```

### Defensive Fallback Strategy

For theoretical compatibility (though all modern browsers support custom cubic‑beziers):

```css
@supports (animation-timing-function: cubic-bezier(0,0,1,1)) {
  .animated {
    animation-timing-function: var(--easing-enter, cubic-bezier(0.77, 0, 0.175, 1));
  }
}
@supports not (animation-timing-function: cubic-bezier(0,0,1,1)) {
  .animated {
    animation-timing-function: ease-out; /* last‑resort generic */
  }
}

```

### Seam‑Masking with Blur Overlays

When crossfading states that overlap, apply subtle blur to mask interpolation artifacts — a technique noted in the audit guidelines:

```tsx
function CrossfadeContainer({ from, to, isTransitioning }) {
  const blur = isTransitioning ? 'blur(2px)' : 'none';
  
  return (
    <div
      style={{
        animation: `crossfade 1s ${easing.enter} forwards`,
        filter: blur,
        willChange: 'opacity, filter',
      }}
    >
      {isTransitioning ? to : from}
    </div>
  );
}

```

## Key Files in the Animation System

| File Path | Purpose |
|-----------|---------|
| [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) | Core motion standards; declares native easings insufficient |
| [`skills/review-animations/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/SKILL.md) | Responsive easing rules and personality matching |
| [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md) | Design‑system token requirements and external curve resources |
| [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md) | Custom cubic‑bezier recommendations |
| [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md) | Checklist flagging `ease‑in` and weak curves as regressions |

## Summary

- **Built‑in CSS easing curves** (`ease`, `ease‑in`, `ease‑out`, `ease‑in‑out`) are designed for prototyping, not production UI
- The `emilkowalski/skills` repository **explicitly forbids** native easings in professional contexts, calling them "too weak"
- **Strong custom cubic‑beziers** enable brand‑aligned, deterministic motion that performs consistently across browsers
- Design‑system **tokens** enforce unified motion language across large teams and codebases
- The **audit rules** in [`AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/AUDIT.md) treat `ease‑in` as a regression because it delays perceived responsiveness

## Frequently Asked Questions

### Why is `ease‑in` specifically problematic for UI animations?

`ease‑in` delays visible motion by starting slowly and accelerating, which creates perceived lag even when the animation technically begins immediately. The [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md) flags any `ease‑in` usage as a finding because it "delays the moment the user is watching," violating the principle that interactive feedback should feel instantaneous.

### What makes a cubic‑bezier "strong" versus "weak"?

According to [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md), a **strong** curve has pronounced asymmetry and steeper slopes — typically starting or ending with acceleration values outside the `0–1` range for more decisive motion. Weak curves (like the built‑in `ease` at `0.25, 0.1, 0.25, 1.0`) stay close to linear, producing gentle, forgettable movement that lacks visual punch.

### How do design tokens solve the browser consistency problem?

By encoding vetted cubic‑bezier values as tokens, teams bypass browser‑specific implementations of generic keywords. The same `cubic-bezier(0.77, 0, 0.175, 1)` calculates identically in Safari, Chrome, and Firefox because the browser evaluates the raw parameters rather than a named preset that may vary by implementation.

### Where should I source production‑ready easing curves?

The `skills` repository recommends [easing.dev](https://easing.dev/) and [easings.co](https://easings.co/) as curated collections. These resources provide parametric values tested for visual quality, often categorized by motion personality (elastic, exponential, circular) that designers can map to component behavior.