Animated blur overlay
September 7, 2023Chrome browser is usually better at rendering CSS backdrop filters than any other browser. That's not the case with one of the filters - blur().
Chrome fails under multiple scenarios:
- unpleasant flickering, when content under the backdrop is moving, or when the backdrop moves beyond the viewport,
- the backdrop-filter: blur() completely breaks when you try to animate it with transition or animation.
I've found a remedy for the second scenario. And the use case for transitioning the backdrop-filter: blur() is quite common - the blur overlay is often displayed behind a modal window and now we'll be able to make a smooth transition between the two states.
To see this effect in action, hover or tap the box below.
The solution
I've discovered that while transitioning the backdrop-filter: blur() property breaks the transition in Chrome, we can transition the blur in a different way. Here's where @property comes to rescue - we can use it to define a custom CSS property and transition it instead.
Now the problem is Firefox does NOT support @property, but we'll make a fallback for it!
.blur-overlay { --end-blur: 20px; --duration: 0.3s; --easing: ease-in-out; position: fixed; inset: 0; } @supports (-moz-appearance: none) { .blur-overlay { transition: var(--duration) backdrop-filter var(--easing); } .blur-overlay[data-state="open"] { backdrop-filter: blur(var(--end-blur)); } .blur-overlay[data-state="closed"] { backdrop-filter: blur(0px); } } @property --overlay-blur { syntax: "<length>"; inherits: false; initial-value: 0px; } @supports not (-moz-appearance: none) { .blur-overlay { transition: var(--duration) --overlay-blur var(--easing); -webkit-backdrop-filter: blur(var(--overlay-blur)); backdrop-filter: blur(var(--overlay-blur)); } .blur-overlay[data-state="open"] { --overlay-blur: var(--end-blur); } .blur-overlay[data-state="closed"] { --overlay-blur: 0px; } }