Home / Snippets / Animation & Motion /

Timing function comparison

Compare CSS easing functions side by side — ease, ease-in, ease-out, ease-in-out, linear, and cubic-bezier in a live animated demo.

ease
ease-in
ease-out
ease-in-out
linear
cubic-bezier(0.34, 1.56, 0.64, 1)
Widely Supported
animationno-js

Quick implementation

<!-- Markup Structure -->
<div class="timing-demo">
  <div class="timing-row timing-row--ease">
    <span class="timing-label">ease</span>
    <div class="timing-track"><div class="timing-dot"></div></div>
  </div>
  <!-- Repeat for other variants -->
</div>

/* CSS */
@keyframes timing-slide {
  0% { transform: translateX(0); }
  100% { transform: translateX(calc(100% + 2rem)); }
}

.timing-row {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.timing-dot {
  width: 1rem;
  height: 1rem;
  background-color: oklch(0.65 0.2 260);
  border-radius: 50%;
  animation: timing-slide 2s infinite;
}

/* Variants */
.timing-row--ease .timing-dot { animation-timing-function: ease; }
.timing-row--ease-in .timing-dot { animation-timing-function: ease-in; }
.timing-row--ease-out .timing-dot { animation-timing-function: ease-out; }
.timing-row--ease-in-out .timing-dot { animation-timing-function: ease-in-out; }
.timing-row--linear .timing-dot { animation-timing-function: linear; }
.timing-row--bounce .timing-dot { animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1); }

/* Pause on hover */
.timing-demo:hover .timing-dot {
  animation-play-state: paused;
}

/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
  .timing-dot { animation: none; }
}

Prompt this to your LLM

Includes role, constraints, and framework variants.

Role: Senior Frontend Engineer specializing in CSS animation.

Goal: Create a visual comparison of CSS timing functions (ease, ease-in, ease-out, linear, cubic-bezier) using a single keyframe animation.

Constraints:
1. Use a single @keyframes definition for movement (translateX).
2. Apply different animation-timing-functions to child elements.
3. Use oklch() for all color values.
4. Include a hover state that pauses animation-play-state.
5. Respect prefers-reduced-motion.

Framework Variants:
A) Vanilla CSS: Use utility classes for timing functions.
B) React/Tailwind: Use arbitrary values for animation-timing-function.

Edge Cases:
1. Handling long labels for complex cubic-bezier values.
2. Ensuring the animation loop is seamless.
3. Accessibility for motion-sensitive users.

Why this matters in 2026

Timing functions are the most misunderstood part of CSS animation. While linear is mathematically simple, it often feels robotic to human eyes. The default ease is a good starting point, but modern interfaces demand more personality. Custom cubic-bezier curves allow us to simulate physics—like the "bounce" effect shown above—without writing complex JavaScript physics engines. Furthermore, the new linear() function (with steps) is becoming essential for scroll-driven animations, allowing precise control over frame-by-frame playback.

The logic

The animation-timing-function property defines the speed curve of an animation. It maps the progress of the animation (0% to 100%) to a value between 0 and 1. A cubic-bezier(0.34, 1.56, 0.64, 1) curve, for instance, allows the value to exceed 1.0 (overshoot) before settling back, creating a spring-like effect. By applying these curves to a shared @keyframes definition, we can isolate the timing behavior from the movement logic.

Accessibility & performance

Performance is generally excellent for these animations because they only affect transform and opacity, which are handled by the GPU compositor. However, accessibility is critical. Always include @media (prefers-reduced-motion: reduce) to disable or simplify animations for users who experience vestibular disorders. Additionally, pausing animations on hover (as demonstrated) is a great UX pattern that allows users to inspect the start and end states of the motion.