agentleFS
soilmasssoilmass/motion-design-agent/skills/blur/SKILL.md

blur

Skill7 starsChanged 10 months agoMITView on GitHub

Blur animations including focus transitions, motion blur, depth of field, and tilt-shift effects. Use when creating focus pull transitions, adding motion blur to fast movements, implementing depth-based blur, or simulating camera lens effects.

The file

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use will-change: filter: before animating

    line 456
  2. Distinctive:

    No additional references needed for this skill

    line 478

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Blur

Blur effects for focus, motion, and depth simulation.

Standards Reference

StandardDocumentation
W3C DTCGdesigntokens.org
CSS Filterdeveloper.mozilla.org/CSS/filter
CSS Backdrop Filterdeveloper.mozilla.org/CSS/backdrop-filter

Quick Reference

Load from: tokens/blur.tokens.json

Blur Radius

TokenValueUse
none0pxSharp, in-focus
subtle2pxSlight softening
light4pxNoticeable softening
medium8pxClear defocus
strong16pxPronounced blur
extreme32pxAbstract softness

Focus Pull Duration

TokenValueUse
pull-duration-fast200msSnap focus
pull-duration-standard400msNatural pace
pull-duration-slow800msCinematic rack focus

Selection Guide

What type of blur?
│
├── FOCUS TRANSITION → Element coming into/out of focus
│   ├── Fast snap → 200ms
│   ├── Standard → 400ms
│   └── Cinematic → 800ms+
│
├── MOTION BLUR → Moving elements
│   ├── Subtle → distance-subtle (4px)
│   ├── Standard → distance-medium (12px)
│   └── Extreme → distance-extreme (48px)
│
├── DEPTH OF FIELD → Foreground/background separation
│   ├── Near blur → near-blur (8px)
│   └── Far blur → far-blur (4px)
│
├── TILT-SHIFT → Miniature effect
│   ├── Narrow band → focus-band-narrow (100px)
│   └── Wide band → focus-band-wide (400px)
│
└── BACKDROP → Background blur behind element
    ├── Subtle → light (4px)
    ├── Standard → medium (8px)
    └── Frosted glass → strong (16px)

Patterns

Focus Pull Transition

Animate blur to simulate camera focus change.

CSS:

.focus-pull {
  transition: filter 400ms ease-out; /* {motion.blur.focus.pull-duration-standard} */
}

.focus-pull.out-of-focus {
  filter: blur(8px); /* {motion.blur.radius.medium} */
}

.focus-pull.in-focus {
  filter: blur(0px); /* {motion.blur.radius.none} */
}

Framer Motion:

const focusVariants = {
  blurred: {
    filter: "blur(8px)", // {motion.blur.radius.medium}
    transition: { duration: 0.4 }
  },
  focused: {
    filter: "blur(0px)",
    transition: { duration: 0.4 }
  }
};

<motion.div
  variants={focusVariants}
  animate={isFocused ? "focused" : "blurred"}
/>

GSAP:

// Focus in
gsap.to(element, {
  filter: "blur(0px)",
  duration: 0.4,
  ease: "power2.out"
});

// Focus out
gsap.to(element, {
  filter: "blur(8px)",
  duration: 0.4,
  ease: "power2.out"
});

Rack Focus (Two Elements)

Shift focus between foreground and background.

JavaScript:

function rackFocus(foreground, background, duration = 0.8) {
  const tl = gsap.timeline();

  tl.to(foreground, {
    filter: "blur(8px)",
    duration: duration / 2,
    ease: "power2.inOut"
  }, 0)
  .to(background, {
    filter: "blur(0px)",
    duration: duration / 2,
    ease: "power2.inOut"
  }, duration / 4); // Slight overlap for smooth transition

  return tl;
}

Framer Motion:

function RackFocus({ focusTarget }) {
  return (
    <>
      <motion.div
        className="foreground"
        animate={{ filter: focusTarget === 'fg' ? 'blur(0px)' : 'blur(8px)' }}
        transition={{ duration: 0.4 }}
      />
      <motion.div
        className="background"
        animate={{ filter: focusTarget === 'bg' ? 'blur(0px)' : 'blur(4px)' }}
        transition={{ duration: 0.4 }}
      />
    </>
  );
}

Motion Blur Effect

Blur in direction of movement.

CSS (approximation with directional blur):

/* Horizontal motion blur using multiple shadows */
.motion-blur-h {
  filter: blur(0px);
  text-shadow:
    -4px 0 2px rgba(0,0,0,0.1),
    -2px 0 1px rgba(0,0,0,0.1),
    2px 0 1px rgba(0,0,0,0.1),
    4px 0 2px rgba(0,0,0,0.1);
}

/* Using SVG filter for true directional blur */
.motion-blur-svg {
  filter: url(#motion-blur);
}

SVG Filter:

<svg>
  <filter id="motion-blur">
    <feGaussianBlur in="SourceGraphic" stdDeviation="12,0" />
    <!-- 12px horizontal, 0px vertical -->
  </filter>
</svg>

Framer Motion (animate blur during motion):

function MovingElement() {
  const x = useMotionValue(0);
  const blur = useTransform(
    useVelocity(x),
    [-1000, 0, 1000],
    [12, 0, 12] // More velocity = more blur
  );

  return (
    <motion.div
      style={{
        x,
        filter: useMotionTemplate`blur(${blur}px)`
      }}
      drag="x"
    />
  );
}

Backdrop Blur (Frosted Glass)

Blur content behind an element.

CSS:

.frosted-glass {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(16px); /* {motion.blur.radius.strong} */
  -webkit-backdrop-filter: blur(16px);
}

/* Animated backdrop blur */
.modal-backdrop {
  backdrop-filter: blur(0px);
  transition: backdrop-filter 300ms ease-out;
}

.modal-backdrop.visible {
  backdrop-filter: blur(8px); /* {motion.blur.radius.medium} */
}

Framer Motion:

<motion.div
  initial={{ backdropFilter: "blur(0px)" }}
  animate={{ backdropFilter: "blur(16px)" }}
  exit={{ backdropFilter: "blur(0px)" }}
  transition={{ duration: 0.3 }}
  style={{ background: "rgba(255,255,255,0.1)" }}
/>

Tilt-Shift Effect

Selective focus band for miniature effect.

CSS (gradient mask + blur):

.tilt-shift-container {
  position: relative;
}

.tilt-shift-blur {
  position: absolute;
  inset: 0;
  filter: blur(16px);
  mask-image: linear-gradient(
    to bottom,
    black 0%,
    transparent 30%,
    transparent 70%,
    black 100%
  );
  pointer-events: none;
}

Advanced Tilt-Shift:

function createTiltShift(container, options = {}) {
  const {
    focusPosition = 0.5, // 0-1, vertical position of focus band
    focusBandSize = 0.3, // 0-1, size of in-focus area
    blurAmount = 16      // px
  } = options;

  const top = (focusPosition - focusBandSize / 2) * 100;
  const bottom = (focusPosition + focusBandSize / 2) * 100;

  const blurLayer = document.createElement('div');
  blurLayer.style.cssText = `
    position: absolute;
    inset: 0;
    filter: blur(${blurAmount}px);
    mask-image: linear-gradient(
      to bottom,
      black 0%,
      black ${top}%,
      transparent ${top + 10}%,
      transparent ${bottom - 10}%,
      black ${bottom}%,
      black 100%
    );
    pointer-events: none;
  `;

  container.style.position = 'relative';
  container.appendChild(blurLayer);

  return {
    updateFocus(newPosition) {
      // Animate focus band position
      gsap.to(blurLayer, {
        maskImage: `linear-gradient(...)`, // Updated gradient
        duration: 0.5
      });
    }
  };
}

Depth-Based Blur

Blur based on z-depth in scene.

CSS Custom Properties:

.depth-element {
  --z-depth: 0; /* 0 = in focus, negative = near, positive = far */
  filter: blur(calc(abs(var(--z-depth)) * 2px));
  transition: filter 200ms ease-out;
}

/* Example depth layers */
.layer-near { --z-depth: -3; } /* 6px blur */
.layer-focus { --z-depth: 0; } /* 0px blur */
.layer-mid { --z-depth: 2; }   /* 4px blur */
.layer-far { --z-depth: 4; }   /* 8px blur */

Framer Motion:

function DepthScene({ focalDistance }) {
  const layers = [
    { z: 100, content: "Near" },
    { z: 300, content: "Focus" },
    { z: 500, content: "Far" }
  ];

  return layers.map(layer => {
    const distance = Math.abs(layer.z - focalDistance);
    const blur = Math.min(distance / 50, 16); // Max 16px blur

    return (
      <motion.div
        key={layer.z}
        animate={{ filter: `blur(${blur}px)` }}
        transition={{ duration: 0.4 }}
      >
        {layer.content}
      </motion.div>
    );
  });
}

Radial/Zoom Blur

Blur radiating from center point.

SVG Filter:

<svg>
  <filter id="radial-blur">
    <feGaussianBlur in="SourceGraphic" stdDeviation="0" result="blur1"/>
    <feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blur2"/>
    <feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur3"/>

    <feImage href="data:image/svg+xml,..." result="gradient"/>

    <feComposite in="blur1" in2="gradient" operator="in" result="masked1"/>
    <!-- Complex compositing for radial effect -->
  </filter>
</svg>

Canvas-based:

function radialBlur(ctx, centerX, centerY, maxBlur, samples = 10) {
  const canvas = ctx.canvas;
  const tempCanvas = document.createElement('canvas');
  tempCanvas.width = canvas.width;
  tempCanvas.height = canvas.height;
  const tempCtx = tempCanvas.getContext('2d');

  // Draw multiple scaled copies with offset
  for (let i = 0; i < samples; i++) {
    const scale = 1 + (i / samples) * 0.1;
    const alpha = 1 / samples;

    tempCtx.globalAlpha = alpha;
    tempCtx.save();
    tempCtx.translate(centerX, centerY);
    tempCtx.scale(scale, scale);
    tempCtx.translate(-centerX, -centerY);
    tempCtx.drawImage(canvas, 0, 0);
    tempCtx.restore();
  }

  ctx.drawImage(tempCanvas, 0, 0);
}

Reduced Motion

For prefers-reduced-motion: reduce:

Full MotionReduced Alternative
Focus pull animationInstant blur change
Motion blurNo blur, or static slight blur
Animated tilt-shiftStatic blur or none
Backdrop blur animationInstant backdrop blur

Implementation:

@media (prefers-reduced-motion: reduce) {
  .focus-pull {
    transition-duration: 0.01ms;
  }

  .motion-blur-h {
    filter: none;
    text-shadow: none;
  }

  .tilt-shift-blur {
    /* Keep static blur, just don't animate */
    transition: none;
  }
}

Performance Considerations

  1. filter: blur() triggers GPU compositing — generally performant
  2. backdrop-filter can be expensive — limit to small areas
  3. Large blur radii (32px+) may cause performance issues
  4. Animated blur works best on simple elements
  5. Use will-change: filter before animating
.blur-animated {
  will-change: filter;
}

.blur-animated.animation-done {
  will-change: auto;
}

Cross-References

  • See reveals/ for blur + reveal combinations
  • See opacity/ for blur + fade combinations
  • See depth/ for 3D depth-based blur
  • See camera/ for cinematic focus effects
  • See motion-blur/ for legacy motion blur tokens

References

  • No additional references needed for this skill

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.