Articles

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.

Takina Takina · · 3 min read
Close-up of CSS code on a dark editor background

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 above 100% 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 above 100% 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 the opacity property, 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 the box-shadow property.

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:

filterbackdrop-filter
Applies toThe element itself and its childrenWhatever is visually behind the element
Common usePhoto effects, disabled-state dimming, hover treatmentsFrosted-glass panels, translucent overlays
Requires transparencyNoYes — 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.

Takina 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.

#CSS #Web Development #Frontend