Filters, in the order they apply
Only the functions you actually changed are emitted — a neutral function does nothing but force a compositing layer.
Filters, in the order they apply
Only the functions you have actually changed are emitted. A neutral function in the list does nothing except force the element onto its own compositing layer.
A filter changes what "fixed" means underneath it
This is the behaviour that costs people an afternoon. An element with any filter other than none becomes a containing block for its positioned descendants — which means a position: fixed child inside it stops being fixed to the viewport and becomes fixed relative to the filtered element instead.
The symptom is a modal, a sticky header or a dropdown that scrolls away with the page, or is clipped, or lands in the wrong place entirely — while the CSS on the element itself is plainly correct. The cause is a filter on an ancestor, possibly several levels up, possibly added for an unrelated hover effect. transform, perspective, backdrop-filter and will-change all do the same thing. If something fixed is misbehaving, search the ancestors for those five properties before suspecting anything else.
filter and backdrop-filter are not variants of each other
filter processes the element and everything inside it: blur an element and its own text blurs with it. backdrop-filter processes whatever is behind the element and leaves its contents untouched, which is why frosted-glass panels use it — the background is blurred and the label on top stays sharp.
The one that catches people is that backdrop-filter needs something to see through. An element with a fully opaque background has no backdrop showing, so the filter computes and is entirely invisible. Semi-transparency is not decoration in that arrangement; it is the mechanism, and a panel that looks solid will never show the effect no matter how large the blur radius.
Order, and cost
Filters apply left to right and the order changes the result: blur(4px) brightness(1.5) brightens a blurred image, brightness(1.5) blur(4px) blurs a brightened one. They are not the same picture.
Any filter other than none promotes the element to its own layer and creates a containing block for fixed and absolute descendants. That last part surprises people: a position: fixed child inside a filtered ancestor is positioned against the ancestor, not the viewport.
blur() is the expensive one, and its cost grows with the radius and the area. On a scrolling list it is the usual cause of dropped frames.
Filters are not colour management
saturate() and hue-rotate() operate on linear-light sRGB with fixed matrices. They are fast and they are approximations — hue-rotate(180deg) is not the perceptual complement, and a fully saturated result is not the same as a colour chosen at that chroma.
For choosing a colour, work in OKLCH. For nudging an image, filters are the right tool.
Greyscale is a useful check
Set greyscale to 100% and see what still reads. Anything that disappears was relying on hue alone, and that is the set of decisions worth revisiting.