CSS Filter Generator
Build a filter or backdrop-filter chain with live preview. Functions apply in order, no-op values are left out, and the stacking context cost is stated.
Enable JavaScript to change the filter; the CSS below is for the defaults.
In pixels. On a filter this blurs the element; on a backdrop-filter it blurs what is behind it.
Applied before sepia, which is why grayscale then sepia gives a sepia image and the reverse gives a grey one.
A dark tint of the background reads better than pure black, which greys out whatever is under it.
Zero for none. Animating a filter is compositor work on most engines, and a large blur is expensive on every frame.
.filtered {
filter: brightness(106%) contrast(112%) saturate(120%) drop-shadow(0px 2px 6px rgb(11 16 32 / 0.35));
}
/* A filter other than none creates a containing block and a stacking
context, so position: fixed inside this element becomes position:
absolute against it, and z-index inside it is scoped to it. */
Two things about CSS filters are worth knowing before the sliders.
They apply in the order they are written, and the order changes the result. grayscale(1) sepia(1) is a
sepia image; sepia(1) grayscale(1) is a grey one. This tool writes them in a fixed order, documented
below, so the preview and the copied CSS never disagree about it.
And a filter is not free. Any value other than none creates a containing block and a new stacking
context on that element, which means position: fixed inside it becomes fixed to it rather than to the
viewport, and z-index inside it is scoped to it. That is the single most common surprise with filters,
and the generated CSS says so in a comment rather than leaving it to be discovered.
How to use
- Move the sliders. Values that do nothing are left out of the output, so
brightness(100%)never appears. - Tick the drop shadow for a shadow that follows the shape rather than the box.
- Tick “filter what is behind it” for
backdrop-filter, which is the frosted-panel effect, and the preview switches to a panel over the image.
Example
A light photographic lift with a soft drop shadow:
.card img {
filter: brightness(106%) contrast(112%) saturate(120%) drop-shadow(0px 2px 6px rgb(11 16 32 / 0.35));
transition: filter 200ms ease;
}
/* A filter other than none creates a containing block and a stacking
context, so position: fixed inside this element becomes position:
absolute against it, and z-index inside it is scoped to it. */
And the frosted panel, with the prefix Safari still wants:
.panel {
-webkit-backdrop-filter: blur(12px) saturate(180%);
backdrop-filter: blur(12px) saturate(180%);
}
The saturate is not decoration. Blurring alone washes out the colour behind a panel, and pushing saturation back up is what makes the frost look like frost rather than fog.
Pitfalls
Order is part of the value. Colour functions are not commutative. If you hand-edit the output, keep the order or expect a different image.
Every filter creates a stacking context. A dropdown that escaped its card with position: fixed will
stop escaping the moment a filter lands on an ancestor. Tooltips, sticky headers and modals are where
this bites.
drop-shadow is not box-shadow. It follows the alpha channel, so it traces the shape of a transparent PNG or an SVG instead of boxing it. It is also more expensive, and it cannot take a spread.
backdrop-filter needs something behind it and something see-through. A fully opaque background hides whatever the filter did. The element needs a partially transparent background colour for the effect to be visible at all.
Safari still wants the prefix. -webkit-backdrop-filter has been required for years and remains the
safer thing to ship, which is why the output includes both.
Blur is expensive. A large blur over a large area costs real time every frame it changes, and animating one is a reliable way to make a page feel slow on a phone.
Filters apply to text too. A contrast or brightness change that flatters an image can push text on top of it below a readable contrast ratio, which is why the preview has words on it.
Compatibility
filter is supported everywhere, including every version of Safari and Edge that is still in use.
backdrop-filter is supported in current Chrome, Edge, Firefox 103 and later, and Safari, which has
needed -webkit-backdrop-filter since it first shipped the feature. Both properties are emitted, in the
order that lets the standard one win where it is understood.
The preview is drawn in CSS rather than loaded as an image, so the tool ships no asset and works offline. The subject carries a gradient, a shape and text, because a filter that looks fine on a flat swatch can make type unreadable.
The chain is built by one function, mirrored in PHP for the first paint, and a case file compares the two on every build: neutral values, a negative blur, a negative hue rotation, a backdrop rule and non-numeric input. That is why the server-rendered CSS and the CSS after hydration are the same string rather than nearly the same.
Frequently asked questions
Why has my position: fixed element stopped being fixed?
none makes that ancestor the containing block for fixed
and absolute descendants, so the element is now positioned against the card rather than the viewport.What is the difference between filter and backdrop-filter?
filter changes the element and everything in it. backdrop-filter changes what is visible behind it,
which is only useful when the element itself is partly transparent.Why does my frosted panel look grey?
saturate(150%) to 180% after the blur and the colour behind the panel
comes back.Is drop-shadow slower than box-shadow?
box-shadow for rectangles and drop-shadow for shapes with transparency.