# No Transitions on Theme Switch

**MUST** · **ID:** `animations-theme-switch-no-transitions` · **Category:** animations
**Source:** [Rauno](https://interfaces.rauno.me/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/animations-theme-switch-no-transitions

> MUST: Suppress `transition` and `animation` on every element while flipping the theme, then restore them on the next frame — otherwise each colour-animating element ripples across the page.

Switching themes should not trigger transitions and animations on elements

When toggling between light and dark mode, elements with CSS transitions will visibly animate their color changes, creating a distracting ripple effect across the page. Temporarily disable transitions during theme switches for an instant, clean change.

## Rule snippet

```tsx
document.documentElement.classList.add("theme-switching");
setTheme(next);
requestAnimationFrame(() => document.documentElement.classList.remove("theme-switching"));
/* .theme-switching *, .theme-switching *::before, .theme-switching *::after { transition: none !important } */
```

## Bad — do not do this

`animations-theme-switch-no-transitions-bad`

```tsx
import { useState } from 'react';

export function ThemeSwitchNoTransitionsBad() {
  const [isDark, setIsDark] = useState(false);

  return (
    <div className="w-full max-w-sm space-y-4">
      <div
        className="rounded-lg p-4 space-y-3 transition-all duration-500"
        style={{
          background: isDark ? '#1a1a2e' : '#ffffff',
          border: `1px solid ${isDark ? '#333' : '#e5e5e5'}`,
          color: isDark ? '#e5e5e5' : '#1a1a2e',
        }}
      >
        <div className="flex items-center justify-between">
          <span className="text-sm font-medium">Theme Toggle</span>
          <button
            onClick={() => setIsDark(!isDark)}
            className="px-3 py-1 rounded text-sm transition-all duration-500"
            style={{
              background: isDark ? '#6366f1' : '#e5e5e5',
              color: isDark ? '#fff' : '#1a1a2e',
            }}
          >
            {isDark ? '☀️ Light' : '🌙 Dark'}
          </button>
        </div>
        <div className="transition-all duration-500 rounded px-3 py-2 text-sm" style={{ background: isDark ? '#252547' : '#f5f5f5' }}>
          Card element
        </div>
        <div className="transition-all duration-500 rounded px-3 py-2 text-sm" style={{ background: isDark ? '#252547' : '#f5f5f5' }}>
          Another element
        </div>
      </div>
      <p className="text-xs text-error">All elements visibly transition during theme switch — distracting</p>
    </div>
  );
}
```

## Good — do this

`animations-theme-switch-no-transitions-good`

```tsx
import { useState, useRef, useCallback } from 'react';

export function ThemeSwitchNoTransitionsGood() {
  const [isDark, setIsDark] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  const toggleTheme = useCallback(() => {
    const el = containerRef.current;
    if (el) {
      el.style.setProperty('--transition-duration', '0s');
      setIsDark(prev => !prev);
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          el.style.removeProperty('--transition-duration');
        });
      });
    }
  }, []);

  return (
    <div className="w-full max-w-sm space-y-4">
      <div
        ref={containerRef}
        className="rounded-lg p-4 space-y-3"
        style={{
          background: isDark ? '#1a1a2e' : '#ffffff',
          border: `1px solid ${isDark ? '#333' : '#e5e5e5'}`,
          color: isDark ? '#e5e5e5' : '#1a1a2e',
        }}
      >
        <div className="flex items-center justify-between">
          <span className="text-sm font-medium">Theme Toggle</span>
          <button
            onClick={toggleTheme}
            className="px-3 py-1 rounded text-sm"
            style={{
              background: isDark ? '#6366f1' : '#e5e5e5',
              color: isDark ? '#fff' : '#1a1a2e',
            }}
          >
            {isDark ? '☀️ Light' : '🌙 Dark'}
          </button>
        </div>
        <div className="rounded px-3 py-2 text-sm" style={{ background: isDark ? '#252547' : '#f5f5f5' }}>
          Card element
        </div>
        <div className="rounded px-3 py-2 text-sm" style={{ background: isDark ? '#252547' : '#f5f5f5' }}>
          Another element
        </div>
      </div>
      <p className="text-xs text-success">Transitions disabled during theme switch — instant, clean change</p>
    </div>
  );
}
```

## References

- [interfaces.rauno.me](https://interfaces.rauno.me/)
- [next-themes](https://github.com/pacocoursey/next-themes)
