CSS filter Property: Blur, Brightness, and More
The CSS filter property applies blur, brightness, contrast, grayscale, and other graphical effects directly to an element, no image editor required.
The CSS filter property applies a graphical effect — blur, brightness, contrast, grayscale, and more — directly to an element and everything inside it, including its own background, borders, and children. It’s the same category of effect you’d reach for in an image editor, except it runs in the browser, responds to hover and state changes, and never touches the underlying image file.
The available filter functions
filter accepts one or more function values, applied in the order they’re listed:
blur(<length>)— Gaussian blur.blur(4px)softens edges; larger values blur more.brightness(<percentage>)— scales luminance.100%is unchanged,0%is black, values above100%overexpose.contrast(<percentage>)— pushes light and dark values further apart or closer together.100%is unchanged.grayscale(<percentage>)— desaturates.100%is fully grayscale.sepia(<percentage>)— applies a sepia (warm brown) tone.saturate(<percentage>)— scales color intensity.0%is grayscale, values above100%oversaturate.hue-rotate(<angle>)— rotates hues around the color wheel, e.g.hue-rotate(90deg).invert(<percentage>)— inverts colors;100%is a full negative.opacity(<percentage>)— like theopacityproperty, but composable with the other filter functions.drop-shadow(<offset-x> <offset-y> <blur> <color>)— a shadow that follows the element’s actual alpha shape, not its box, which is what sets it apart from thebox-shadowproperty.
Multiple functions chain in a single declaration:
.photo {
filter: grayscale(60%) contrast(110%) brightness(95%);
}
Each function is evaluated in sequence, so blur(4px) invert(100%) produces a different result than invert(100%) blur(4px) when combined with other effects — order matters the same way it does for transform.
filter vs backdrop-filter
These two properties are easy to confuse because they share syntax, but they target different things:
filter | backdrop-filter | |
|---|---|---|
| Applies to | The element itself and its children | Whatever is visually behind the element |
| Common use | Photo effects, disabled-state dimming, hover treatments | Frosted-glass panels, translucent overlays |
| Requires transparency | No | Yes — the element needs a semi-transparent background to reveal the effect |
If you want to dim or desaturate an image, use filter. If you want a navigation bar to blur the content scrolling underneath it, that’s backdrop-filter. See that article for the frosted-glass pattern in detail.
Practical patterns
Dimming a disabled or loading state:
.card[aria-disabled="true"] {
filter: grayscale(80%) opacity(60%);
}
A hover effect that doesn’t repaint layout:
.thumbnail {
filter: brightness(90%);
transition: filter 0.15s ease;
}
.thumbnail:hover {
filter: brightness(105%) saturate(115%);
}
Because filter is a compositor-friendly property in most browsers, animating it tends to stay smooth even on lower-powered devices — similar to animating transform or opacity, and unlike animating properties that trigger layout. See the CSS transforms guide for the broader category of GPU-accelerated properties, and the transitions vs. animations piece for choosing between the two when you build effects like this.
A drop shadow that hugs transparent PNG or SVG content:
.icon {
filter: drop-shadow(0 4px 6px rgb(0 0 0 / 0.3));
}
Unlike box-shadow, which draws a shadow around an element’s rectangular box, drop-shadow respects alpha transparency — a shadow on a star-shaped icon follows the star’s outline, not its bounding box.
Performance and accessibility notes
filter is generally cheap to animate because most browsers hand it to the compositor rather than re-running layout or paint on every frame — the same reason it pairs well with the GPU-friendly properties covered in the Core Web Vitals guide. Large blur radii are the exception: blur() with a big pixel value can still be expensive on large elements, especially on low-end mobile GPUs, so test on real hardware rather than assuming it’s free.
For accessibility, be careful with filters that reduce contrast (heavy brightness or opacity reductions) on interactive elements — they can make focus states or text hard to read. Effects that involve motion, such as an animated hue-rotate or pulsing blur, should respect a user’s motion preference; wrap them in a prefers-reduced-motion media query rather than always running them.
The takeaway
filter gives you image-editor-style effects — blur, brightness, contrast, grayscale, drop shadows, and more — as a single CSS property that composes, animates cheaply, and responds to state changes without touching an image file. Reach for it on the element itself; reach for backdrop-filter when the effect needs to apply to whatever sits behind a translucent element instead. Chain functions deliberately, since order changes the result, and keep an eye on blur cost and contrast when you use it on interactive or animated UI.
Tagged
Keep reading
Takina · · 4 min read CSS @starting-style Explained: Entry Transitions in CSS
CSS @starting-style defines an element's before-state on first render, so transitions can animate elements as they appear, even from display: none.
Takina · · 4 min read Container Query Units: cqw, cqh, and cqi Explained
Container query units like cqw and cqi size elements relative to their containing element, not the viewport — here's how and when to use them.
Takina · · 4 min read CSS Relative Color Syntax: Deriving Colors from Colors
Relative color syntax lets CSS derive a new color from an existing one by adjusting its channels directly, no preprocessor or JS required.