CSS Filters and Backdrop Filter
filter vs backdrop-filter — blur, saturate, and glass effects, stacking costs, and accessibility pitfalls for frosted UI.
- css
- filters
- backdrop-filter
filter paints an effect on an element and its contents. backdrop-filter samples what’s behind the element (through its transparent areas) and filters that, which is how “frosted glass” panels work.
Docs: MDN filter, MDN backdrop-filter.
filter: the element itself
.avatar-muted {
filter: grayscale(1) opacity(0.85);
}
.icon:hover {
filter: brightness(1.1);
}
.hero-img.is-loading {
filter: blur(12px);
}
Common functions: blur(), brightness(), contrast(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), sepia(), drop-shadow().
drop-shadow() follows alpha shape (good for non-rect icons) unlike box-shadow.
.logo {
filter: drop-shadow(0 2px 4px rgb(0 0 0 / 0.35));
}
Multiple functions space-separate in one filter value; order matters.
backdrop-filter: frosted chrome
.topbar {
position: sticky;
top: 0;
background: rgb(255 255 255 / 0.72);
backdrop-filter: blur(12px) saturate(1.2);
-webkit-backdrop-filter: blur(12px) saturate(1.2); /* still useful in some engines */
}
Requirements that people miss:
- The element needs partial transparency — fully opaque background hides the backdrop.
- Something visible must scroll/paint behind it.
- Stacking contexts and overflow clipping can prevent sampling.
.modal-panel {
background: color-mix(in srgb, var(--surface) 70%, transparent);
backdrop-filter: blur(16px);
border: 1px solid rgb(255 255 255 / 0.4);
}
Performance and layers
Filters can promote layers and are not free:
- Large
blur()radii are expensive, especially animated. backdrop-filterre-samples as content moves — scroll under a full-width frosted header costs more than a solid header.- Prefer static blur over animating blur radius every frame.
@media (prefers-reduced-transparency: reduce) {
.topbar {
background: var(--surface-solid);
backdrop-filter: none;
}
}
Also respect prefers-reduced-motion if filters are animated.
Accessibility
- Don’t rely on
filter: grayscalealone to mean “disabled.” - Frosted text over busy backgrounds can fail contrast — add a stronger scrim.
invert()for “dark mode” breaks images and brand colors; use real theme tokens.
Worked: dimmed non-modal layer
.route-loading .app-shell {
filter: grayscale(0.2) brightness(0.97);
pointer-events: none;
user-select: none;
}
This mutes the whole shell; fine for brief states, bad for permanent UI.
Interview out-loud
“filter affects the element and its descendants’ rendering. backdrop-filter filters what’s behind a semi-transparent element — glassmorphism. I keep blur radii modest, ensure translucent backgrounds, and provide solid fallbacks when backdrop-filter isn’t supported or the user prefers reduced transparency. Filters have GPU cost, especially on scroll.”
Footguns
- Opaque backgrounds with
backdrop-filter— no visible effect. - Forgetting parent
overflow: hiddenclipping the backdrop sample. - Animating huge blurs on mobile.
- Using
filter: opacity()instead ofopacitywithout knowing it creates different stacking behavior. - Double-applying filters on parent and child until colors look muddy.
Compositing notes
filter on a parent flattens descendants into a single filtered group for many purposes. That can break expected position: fixed containing blocks and create stacking contexts you did not plan. Prefer filtering a leaf image/icon over the whole app shell.
/* Prefer leaf */
.thumb img { filter: grayscale(0.2); }
/* Costly + side effects */
.app-shell.is-dimmed { filter: brightness(0.9); }
backdrop-filter fallbacks
.topbar {
background: rgb(255 255 255 / 0.95); /* solid-ish fallback first */
}
@supports (backdrop-filter: blur(8px)) {
.topbar {
background: rgb(255 255 255 / 0.65);
backdrop-filter: blur(12px) saturate(1.15);
}
}
Test over busy hero videos — frost that looks fine on a flat gray fails on high-frequency backgrounds. Increase scrim opacity before increasing blur radius; blur is the expensive knob.
SVG filters
filter: url(#goo) can reference SVG filter primitives for advanced effects. Keep them rare in product UI; they are harder to theme and reason about in DevTools than CSS function filters.
Related
- blend-mode basics
- transform and opacity performance
- Stacking contexts and z-index
- prefers-reduced-motion
Further reading
Related guides
- Accent Color and Form ControlsUse accent-color to theme native checkboxes, radios, ranges, and progress — what it paints, what it skips, and when to custom-style instead.
- Auto-fit vs Auto-fillauto-fit collapses empty tracks; auto-fill keeps them. Use both with minmax for responsive card grids without media-query soup.
- BEM Naming MethodologyBlock, Element, Modifier naming for CSS — how it limits specificity wars, what to name, and when utility or CSS modules beat strict BEM.
- blend-mode Basicsmix-blend-mode vs background-blend-mode — how pixels combine, isolation, and the stacking/readability traps in product UI.
- box-sizing border-boxWhy border-box makes width include padding and border, the global reset pattern, and the layout bugs content-box still causes.