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
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
| Function | Example | Description |
|---|---|---|
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.
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:
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
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
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:
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()anddrop-shadow()are the most computationally expensive filters — use moderate values and test on lower-end devices.- When animating opacity alone, prefer the dedicated
opacityAnimationVar over theopacity()filter function — see Opacity for details.