Understanding CSS filters
Eight functions, one GPU-shader.
The CSS filter functions every browser supports, what each one does at the pixel level, and why backdrop-filter is its own thing.
The eight functions.
CSS filters apply image-processing operations to any element. The eight that ship in every browser: blur(8px), brightness(1.2), contrast(1.5), grayscale(100%), hue-rotate(45deg), invert(100%), saturate(0.8), sepia(80%). Plus drop-shadow (similar to box-shadow but follows alpha-channel edges) and opacity (functionally identical to the standalone opacity property). Compose multiple in one declaration: filter: blur(2px) brightness(0.7).
filter vs backdrop-filter.
filter processes the element itself — blur an image, desaturate a hovered card. backdrop-filter processes whatever sits behind the element — the frosted-glass effect of macOS, iOS, modern web modals. The element's own content stays sharp; everything you can see through it (semi-transparent backgrounds) gets the filter applied. Different operation, different visual register.
A worked composition.
A vintage-photo look: filter: sepia(80%) contrast(1.1) saturate(0.7) brightness(1.05). The chain is applied in order: sepia tints toward brown, contrast deepens shadows, saturation pulls back, brightness lifts the midtones. Tinker with each value while previewing — the right combination is the one that "feels" right, not a number any guide can give you in advance.
Vintage photo
sepia + contrast + saturate + brightness
Each function operates on the result of the previous.
filter: sepia(80%) contrast(1.1) saturate(0.7) brightness(1.05)
= Faded warm look
Performance — most are free.
CSS filters run on the GPU. The cheap ones (brightness, contrast, hue-rotate, saturate, sepia, invert, grayscale) are simple pixel transforms — almost no performance cost on modern hardware. The expensive ones: blur(proportional to blur radius squared, large blurs hurt), and drop-shadow on transparent images with complex alpha (the renderer has to trace the alpha edge). For animations of expensive filters, prefer opacity or transform overlays.
Stacking context, the gotcha.
Applying a filter creates a new stacking context. Elements inside the filtered parent can't escape its bounding box with negative margins or absolute positioning that crosses outside. The most common bug: a tooltip inside a card with filter: blur(0) (used as a hack for a different reason) gets clipped inside the card's box. The fix is move the tooltip outside, or drop the filter on the parent.
When SVG filters fit.
The CSS filter functions are presets. For arbitrary image processing — colour matrices, custom convolutions, displacement maps, turbulence — use SVG filters referenced from CSS: filter: url(#myFilter). Define an <svg><filter> in the page; CSS picks it up. Far more capable than the function set; far less frequently needed.