Skip to main content
ExodeUI

EXODEUI DESKTOP

A little space for good ideas.

Choose your platform to get the official ExodeUI installer.

Looking for Intel Mac or other builds? Explore the web studio or check all download options.

Prefer the browser? Try for free in your browser →
LanguageEnglish
Motion technique7 min read·Updated October 2026·By the ExodeUI team

How to Animate a Dark Mode Theme Transition

Techniques for smooth dark mode theme transitions: global CSS color crossfades, circular ripple reveals using the View Transitions API, and icon morphing.

Direct Summary & Definition

Core Takeaway

Animating dark mode requires balancing visual smoothness with performance. For a simple site, a 200ms CSS transition on background-color and color is sufficient. For a modern app, use the View Transitions API with a circular clip-path expanding outward from the toggle button, paired with an icon morph from sun to moon.

The pitfall of universal transition: all

Applying transition: all 300ms to every DOM element causes severe performance lag during theme changes because the browser recalculates layout for hundreds of nodes simultaneously. Only transition background-color, border-color, and color on container elements.

The View Transitions API circular reveal

The modern standard for dark mode animations is document.startViewTransition(). By combining it with a circular clip-path starting from the cursor or toggle switch, you create a ripple reveal that illuminates or darkens the entire interface in a single compositor pass.

  • Start theme update inside document.startViewTransition()
  • Calculate click coordinates (x, y) to originate the clip-path circle
  • Animate clip-path: circle(0px) to circle(maxRadius)
  • Morph toggle icon from sun rays to moon crescent using SVG path interpolation

Handling local storage and flash of unstyled theme

Never animate the theme transition during the initial page load. Read the stored theme synchronously in an inline head script so the page renders in the correct theme on frame 0, and only enable transitions for user-initiated clicks.

Accessibility and photosensitivity

Sudden full-screen brightness shifts can trigger ocular strain or seizures. Keep the transition duration moderate (250-400ms) and skip the circular reveal when prefers-reduced-motion is active.

Production Implementation Snippet

Interactive Component Implementation
/* View Transitions API circular reveal */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

::view-transition-new(root) {
  animation: reveal-theme 400ms ease-out;
}

@keyframes reveal-theme {
  from { clip-path: circle(0% at var(--click-x) var(--click-y)); }
  to { clip-path: circle(150% at var(--click-x) var(--click-y)); }
}

Key Principles to Remember

  • Never use transition: all *; target specific color properties only
  • Use the View Transitions API for modern circular ripple reveals
  • Prevent transition flashes on initial page render
  • Provide immediate theme switching when reduced motion is requested

Frequently Asked Questions

Sources

  1. View Transitions API — W3C
  2. Smooth theme transitions with View Transitions — Chrome Developers

Related Guides & Examples

Animate theme states with clean compositor passes.

ExodeUI models theme tokens and state machines in one open .exode file. Try it free on the Community plan.

Open the playground
Try for free