CSS: Workaround to backdrop-filter?

HtmlCss

Html Problem Overview


backdrop-filter is a recent CSS feature, that is not yet available in modern browsers (at least as of July 1, 2016).

  • Chrome 51 supports backdrop-filter via Experimental Web Platform flag.
  • Safari 9.1 supports it with -webkit- prefix
  • Firefox 47 have no support

Being in such an unusable state, I would like to know whether there exists any alternative way to bring in the same result.

JS workarounds for blur, grayscale,… are also welcome

The development of backdrop-filter can be tracked through https://bugs.chromium.org/p/chromium/issues/detail?id=497522

Html Solutions


Solution 1 - Html

I use this to get the popular frosted glass effect. Until someone successfully invents a good polyfill for backdrop-filter I'm using a slightly transparent background as a fallback:

/* slightly transparent fallback */
.backdrop-blur {
  background-color: rgba(255, 255, 255, .9);
}

/* if backdrop support: very transparent and blurred */
@supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
  .backdrop-blur {
    background-color: rgba(255, 255, 255, .5);
    -webkit-backdrop-filter: blur(2em);
    backdrop-filter: blur(2em);
  }
}

The filter will work in currently supported browsers. (Safari and Chrome with experimental Web Platform features enabled) The code should also work in future browsers that support unprefixed backdrop-filter if the spec doesn't change before that.

Examples without and with backdrop-filter support:

transparent fallback blurred

Solution 2 - Html

Update as of 5/01/22:

Backdrop Filter has received further support, check the link for the versions of each browser that support it and a quick tutorial.

Syntax:

.element {
            backdrop-filter: <filter-function> [<filter-function>]* | none
         }

Older Solution

I don't know if you're still chasing this question, but for other users in future:

This effect can be accomplished as follows with CSS Pseudo-Classes, no JavaScript is necessary! shown below:

body,
main::before {
  background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/80625/tree.jpg) 0 / cover fixed;
}

main {
  margin: 100px auto;
  position: relative;
  padding: 10px 5px;
  background: hsla(0, 0%, 100%, .3);
  font-size: 20px;
  font-family: 'Lora', serif;
  line-height: 1.5;
  border-radius: 10px;
  width: 60%;
  box-shadow: 5px 3px 30px black;
  overflow: hidden;
}

main::before {
  content: '';
  margin: -35px;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  filter: blur(20px);
  z-index: -1;
}

<main>
  <blockquote>"The more often we see the things around us &#45; even the beautiful and wonderful things &#45; the more they become invisible to us. That is why we often take for granted the beauty of this world: the flowers, the trees, the birds, the clouds &#45;
    even those we love. Because we see things so often, we see them less and less."
    <footer>&mdash;
      <cite>
        Joseph B. Wirthlin
      </cite>
    </footer>
  </blockquote>
</main>

Live example can be seen on Codepen: https://codepen.io/jonitrythall/pen/GJQBOp

Quick Note:

Depending on the structure of your HTML document, your z-indexes may be different to the one described in the example.

Solution 3 - Html

As of Chrome M76, backdrop-filter is now shipped, unprefixed, and without a needed flag.

https://web.dev/backdrop-filter/

NOTE: (since this answer keeps getting downvoted because Mozilla hasn’t yet shipped it): this feature is available in Safari, Chrome, and Edge, but not yet in Firefox. Mozilla is planning to ship it very soon, but hasn’t yet. So this answer doesn’t contain a “workaround” but simply more information about which browsers require a workaround. Which still seems like useful information.

Solution 4 - Html

Use SVG filters. They work like a charm. Checkout this example CodePen.

backdrop-filter is now supported by default in Chrome Canary. It's also in the 2019 priority list for Firefox development. So, it will soon be supported across all browsers, but for now you can use SVG filters.

Update

SVG filters don't work exactly like backdrop-filter. It's only a workaround and it doesn't work if there's moving elements beneath it. Anyway, I think we're going to be able to use backdrop-filter in production very soon. It's now enabled by default in Chrome Beta! Which also means Edge.

Solution 5 - Html

Just want to add specific workaround that works for me, maybe it's useful for someone out there.

The idea is to wrap every element that should be behind the popup into .blurred and make it blur with filter: blur(10px); (which has better browser support) to it, but then the popup element itself should be outside .blurred.

in code it looks like this:

.blurred {
    position: relative;
    z-index: 0;
    filter: blur(4px);
}

.popup {
    position: absolute;
    z-index: 1;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

.popup__box {
    margin-top: 20px;
    background-color: rgba(255, 0, 0, .1);
 }

<div class="blurred">
  <div>Maybe a navbar goes here</div>
  <h3>Hi, I'm blurred</h3>
  <img src="https://filesamples.com/samples/image/jpg/sample_640%C3%97426.jpg" alt="sample"/>
  <div>Maybe a footer goes here</div>
</div>

<div class="popup">
  <div class="popup__box">
    Hi, I'm a popup
  </div>
</div>

The downside to this workaround is that you have to wrap everything inside the .blurred class, which can be hard (at least for me) sometimes to manage the z-index with other element outside.

Solution 6 - Html

As explained on this page changing the value of the preference layout.css.backdrop-filter.enabled from false to true on the about:config page seems to work for me.

I'm using Firefox Developer 87.0b1 (64 bits)

Solution 7 - Html

I think this is a good solution to wokraround backdrop-filter, but not the same:

you can use it with @supports css rule

@supports not (backdrop-filter: blur(4px)) {
    body > *:not(#element) {
        filter: blur(4px);
    }
}

body > *:not(#element) { /* select every child element in body but not the specified one*/
    background: #9fe2ff;
    filter: blur(4px);
}
#element {
    position: absolute;
    top:20%;
    left:10%;
    background-color: #ffffff;
    z-index:10;
}
div, p {
    margin: 5px;
    padding: 10px;
}

    

<body>
    <div>div element with some text</div>
    <p>paragraph with another text</p>
    <div id="element">Not blured element</div>
    <div>Another div with blured text</div>
    <p>another p </p>
</body>

Solution 8 - Html

You could try to add different filters to the background images:

https://css-tricks.com/almanac/properties/f/filter/

The downfall to this, is that it only works on images.

Basically, there are 10 built-in filters for the CSS filter property:

  • blur(px)
  • brightness(%)
  • contrast(%)
  • drop-shadow(h-shadow v-shadow blur spread color)
  • grayscale(%)
  • hue-rotate(deg)
  • invert(%)
  • opacity(%)
  • saturate(%)
  • sepia(%)

And additionally, you can provide it an url, wich contains an XML file with the appropariate filter.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionryanafrish7View Question on Stackoverflow
Solution 1 - HtmlDuvraiView Answer on Stackoverflow
Solution 2 - HtmlKronoView Answer on Stackoverflow
Solution 3 - HtmlMason FreedView Answer on Stackoverflow
Solution 4 - HtmlAhmedView Answer on Stackoverflow
Solution 5 - HtmlAlvin NovianView Answer on Stackoverflow
Solution 6 - Htmljestin-gView Answer on Stackoverflow
Solution 7 - Htmlmandel99View Answer on Stackoverflow
Solution 8 - HtmlBálintView Answer on Stackoverflow