CSS Filters

Apply animated blur, grayscale, brightness, contrast, and other CSS filter effects.

The filter property animates CSS filter effects — blur, brightness, contrast, and more. Pass a standard CSS filter string to from or to.

Basic Usage

typescript
import { Motion } from "@motion.page/sdk";

Motion("blur-in", ".element", {
  from: { filter: "blur(10px)" },
  duration: 0.8,
  ease: "power2.out",
}).play();

Since an element’s natural CSS has no filter applied (equivalent to none), using from only is sufficient — the SDK reads the current computed state as the to endpoint automatically.

Available Filter Functions

FunctionExampleDescription
blur()blur(10px)Gaussian blur
brightness()brightness(1.5)Adjust brightness (1 = normal)
contrast()contrast(200%)Adjust contrast (100% = normal)
grayscale()grayscale(100%)Convert to grayscale (0% = normal)
hue-rotate()hue-rotate(90deg)Rotate hue along the color wheel
invert()invert(100%)Invert colors
saturate()saturate(200%)Adjust saturation (100% = normal)
sepia()sepia(100%)Apply sepia tone
opacity()opacity(50%)Adjust opacity via filter (100% = fully visible)
drop-shadow()drop-shadow(4px 4px 10px rgba(0,0,0,0.5))Add a drop shadow

Note: In the Motion.page Builder, filters are configured via the Filter property panel where each filter type has its own dedicated control. The SDK accepts the CSS filter string directly.

Combining Multiple Filters

Chain multiple filter functions in a single string, separated by spaces. The SDK interpolates each function value independently.

typescript
Motion("dramatic", ".hero-image", {
  from: { filter: "blur(8px) brightness(0.6) saturate(0)" },
  duration: 1.2,
  ease: "power2.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" });

Common Patterns

Blur + Opacity Reveal

The classic “blur in” pattern combines filter blur with opacity for a polished entrance:

typescript
Motion("blur-reveal", ".card", {
  from: { opacity: 0, filter: "blur(12px)" },
  duration: 0.8,
  stagger: 0.1,
  ease: "power2.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" });

Grayscale to Color on Hover

typescript
Motion("colorize", ".photo", {
  from: { filter: "grayscale(100%)" },
  duration: 0.5,
  ease: "power2.out",
}).onHover({ each: true, onLeave: "reverse" });

Using from only means the element starts fully grayscale and animates to its natural (unfiltered) state on hover. On leave, the animation reverses back to grayscale.

Brightness Pulse

typescript
Motion("pulse", ".cta-button", {
  to: { filter: "brightness(1.3)" },
  duration: 0.6,
  repeat: { times: -1, yoyo: true },
}).play();

Explicit Both Endpoints

When neither endpoint matches the element’s natural state, declare both from and to:

typescript
Motion("filter-shift", ".banner", {
  from: { filter: "hue-rotate(0deg) saturate(100%)" },
  to: { filter: "hue-rotate(180deg) saturate(200%)" },
  duration: 2,
}).onScroll({ scrub: true });

This is the right pattern for scrubbed scroll animations where you want precise control over both the start and end filter state.

Performance

  • CSS filter animations are GPU-accelerated in most browsers, making them performant for visual effects.
  • blur() and drop-shadow() are the most computationally expensive filters — use moderate values and test on lower-end devices.
  • When animating opacity alone, prefer the dedicated opacity AnimationVar over the opacity() filter function — see Opacity for details.