CSS Transitions vs Keyframes for Interruptible UI Animations: When to Use Each

CSS transitions are retargetable mid-animation, making them ideal for interruptible UI; @keyframes always restart from frame 0, causing jarring jumps when interrupted.

Choosing between CSS transitions and @keyframes animations directly impacts how fluidly your interface responds to rapid user input. This guide draws from the animation standards defined in the emilkowalski/skills repository to explain why interruptibility matters and how to implement it correctly.


What Makes an Animation Interruptible?

An interruptible animation can respond to new input without visual discontinuity. When a user toggles a toast, closes a modal, or drags a panel, the motion should adapt smoothly rather than snapping or restarting.

According to skills/review-animations/STANDARDS.md:

"CSS transitions can be interrupted and retargeted mid‑animation; keyframes restart from zero. For anything triggered rapidly (toasts being added, toggles), transitions are smoother."

This distinction forms the foundation of the repository's motion philosophy.


CSS Transitions: The Retargetable Choice

CSS transitions excel at responsive, state-based motion. When a property's target value changes during an active transition, the browser calculates a new path from the current intermediate state to the updated target.

Key Characteristics

Aspect Behavior
Retargetability ✅ Smooth continuation from current state
Implementation Single transition declaration
Performance GPU-accelerated for transform/opacity
Best for Toggles, toasts, hover states, collapsible panels

Practical Example: Interruptible Toast

<div class="toast">New message</div>

<style>
.toast {
  opacity: 0;
  transform: translateY(100%);
  transition: opacity 400ms ease, transform 400ms ease;
}
.toast[data-visible] {
  opacity: 1;
  transform: translateY(0);
}
</style>

<script>
function showToast() {
  const el = document.querySelector('.toast');
  el.dataset.visible = "";
  // Rapid subsequent calls retarget the transition smoothly
}
</script>

Calling showToast() repeatedly before the previous animation completes does not restart from hidden—the toast simply adjusts its trajectory toward visible. This pattern appears throughout skills/find-animation-opportunities/SKILL.md for accordion panels, dropdown menus, and notification stacks.


CSS Keyframes: The Sequential Choice

@keyframes animations always execute their defined sequence from the beginning. When restarted or when play state changes, the animation jumps to frame 0, regardless of current progress.

Interruptibility Problem

@keyframes logoFadeIn {
  from { opacity: 0; transform: scale(0.9); }
  to   { opacity: 1; transform: scale(1); }
}
.logo {
  animation: logoFadeIn 800ms ease-out forwards;
}

If this animation is interrupted and retriggered, the element snaps back to 90% scale and zero opacity before fading in again. For rapid interactions, this creates visual discontinuity.

When Keyframes Are Appropriate

  • One-off entrance sequences (splash screens, brand reveals)
  • Decorative loops (loading spinners, background ambient motion)
  • Fixed timing choreography where interruption is never expected

As noted in skills/improve-animations/AUDIT.md, keyframes should be replaced with transitions for any UI element that responds to user actions.


Real-Time Gestures: Beyond Both Options

When animation must follow continuous user input (drag, swipe, momentum), neither CSS transitions nor keyframes provide sufficient control. The repository recommends spring-based motion via the Web Animations API (WAAPI) or JavaScript libraries.

WAAPI Example: Gesture-Driven Panel

const panel = document.querySelector('.sheet');
let anim = panel.animate(
  [{ transform: 'translateX(0)' }, { transform: 'translateX(-100%)' }],
  { duration: 500, easing: 'cubic-bezier(0.23,1,0.32,1)', fill: 'forwards' }
);

// Update target on the fly—the animation retargets instantly
function updateTarget(percent) {
  anim.effect.updateTiming({ duration: 500 * (1 - percent) });
}

This approach, documented in STANDARDS.md, preserves interruptibility while enabling physics-based response to gesture velocity.


Decision Framework from the Repository

The Emil Design Engineering skill file provides explicit guidance in skills/emil-design-eng/SKILL.md:

"Use CSS transitions over keyframes for interruptible UI … CSS transitions can be interrupted and retargeted mid‑animation; keyframes restart from zero."

Apply this hierarchy:

  1. Default to transitions for any property that changes based on state or user action
  2. Reserve keyframes for static, non-interruptible sequences
  3. Implement springs when real-time input drives the motion

Performance Considerations

Both transitions and keyframes achieve GPU acceleration when limited to compositor-friendly properties:

  • transform (translate, scale, rotate)
  • opacity

However, keyframes carry hidden costs when interrupted. The forced restart can trigger:

  • Layout recalculation if position-dependent properties animate
  • Paint operations for properties affecting visual appearance
  • Frame drops from main-thread work during the jump

Transitions avoid this by maintaining continuous computation on the compositor thread.


Summary

  • CSS transitions retarget smoothly from current state when values change—essential for any UI that toggles rapidly
  • @keyframes animations restart from frame 0, creating jarring discontinuities when interrupted
  • Reserve keyframes strictly for one-off, non-interactive sequences like brand reveals
  • Use springs (WAAPI or JS) for gesture-driven motion requiring real-time response
  • Animate only transform and opacity to maintain 60fps performance on both techniques

Frequently Asked Questions

Why do my keyframe animations feel "janky" on repeated clicks?

@keyframes animations always restart from the first keyframe when retriggered. If a user clicks rapidly, each restart forces the element to jump back to its initial state before animating forward. Replace with CSS transitions to enable smooth retargeting from the current position.

Can I interrupt a CSS transition and reverse it immediately?

Yes. Changing the target class or property value mid-transition causes the browser to calculate a new path from the current computed value to the new target. This produces natural, spring-like motion without JavaScript.

When is Web Animations API preferred over CSS transitions?

WAAPI becomes necessary when animation must respond to continuous input like drag gestures or momentum scrolling. CSS transitions handle discrete state changes; WAAPI provides programmatic control for real-time physics simulation.

Are there accessibility concerns with interruptible animations?

Rapid motion can trigger vestibular disorders. The repository's standards in STANDARDS.md recommend respecting prefers-reduced-motion media queries, which should disable or simplify both transitions and keyframes regardless of interruptibility.

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 →