# Never Animate Large or Continuous Blur

**NEVER** · **ID:** `performance-ibelick-no-blur-animation` · **Category:** performance
**Source:** [@Ibelick](https://www.ui-skills.com/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/performance-ibelick-no-blur-animation

> NEVER: Animate large blur() or backdrop-filter surfaces. They are expensive paint operations that cause frame drops, especially on mobile devices.

Never animate blur on a large surface or on a loop — a small (≤8px), short, one-time blur is the permitted exception

Blur is expensive because it samples a neighbourhood of pixels for every pixel it produces: the cost scales with the AREA blurred and, worse, with the RADIUS, and animating it re-rasterizes the whole surface every frame. So the three variables are radius, area and duration — and ibelick prices all three rather than banning the property outright. The permitted case is a small radius (≤8px), on a small surface, running once. The forbidden cases are the ones that multiply: a full-screen backdrop-filter, a 40px radius, or any blur on a loop. Reach for opacity and translate first; where you truly need a big blur, pre-render it as a static layer and crossfade THAT with opacity, which is composited. IMPORTANT — this is what licenses animations-emil-blur-crossfade, which prescribes filter: blur(2px) during a crossfade to fuse two overlapping states. Under the old blanket phrasing ("never animate blur") the two principles in this corpus flatly contradicted each other. They do not: 2px, on one element, for the length of a transition, is exactly the small/short/one-time carve-out upstream defines. The threshold is the rule; the blanket ban was our overreach.

## Bad — do not do this

`performance-ibelick-no-blur-animation-bad`

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

export function IbelickNoBlurAnimationBad() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="space-y-4">
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="px-4 py-2 bg-primary text-primary-foreground rounded-lg"
      >
        Toggle Overlay
      </button>
      {isOpen && (
        <div
          className="fixed inset-0 flex items-center justify-center z-50"
          style={{
            animation: 'blurIn 500ms ease-out forwards',
          }}
        >
          <div className="absolute inset-0 bg-black/50" style={{ backdropFilter: 'blur(var(--blur))' }} />
          <div className="relative bg-background p-6 rounded-lg shadow-lg">
            <p>Modal content</p>
            <button onClick={() => setIsOpen(false)} className="mt-4 text-sm underline">Close</button>
          </div>
        </div>
      )}
      <style>{`
        @keyframes blurIn {
          from { --blur: 0px; }
          to { --blur: 8px; }
        }
      `}</style>
      <p className="text-xs text-destructive">
        Animating backdrop-filter causes severe jank on most devices
      </p>
    </div>
  );
}
```

## Good — do this

`performance-ibelick-no-blur-animation-good`

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

export function IbelickNoBlurAnimationGood() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="space-y-4">
      <button
        onClick={() => setIsOpen(!isOpen)}
        className="px-4 py-2 bg-primary text-primary-foreground rounded-lg"
      >
        Toggle Overlay
      </button>
      {isOpen && (
        <div className="fixed inset-0 flex items-center justify-center z-50">
          {/* Static blur, animated opacity */}
          <div
            className="absolute inset-0 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200"
          />
          <div className="relative bg-background p-6 rounded-lg shadow-lg animate-in fade-in slide-in-from-bottom-4 duration-200">
            <p>Modal content</p>
            <button onClick={() => setIsOpen(false)} className="mt-4 text-sm underline">Close</button>
          </div>
        </div>
      )}
      <p className="text-xs text-success">
        Static blur with opacity fade - smooth 60fps animation
      </p>
    </div>
  );
}
```

## References

- [ibelick — baseline-ui SKILL.md](https://github.com/ibelick/ui-skills/blob/main/skills/baseline-ui/SKILL.md)
- [ibelick — fixing-motion-performance SKILL.md](https://github.com/ibelick/ui-skills/blob/main/skills/fixing-motion-performance/SKILL.md)
- [MDN — filter](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/filter)
- [CSS Filter Performance](https://web.dev/articles/simplify-paint-complexity-and-reduce-paint-areas)
