How can I make a CSS glass/blur effect work for an overlay?
Asked Answered
S

13

196

I am having trouble applying a blur effect on a semi-transparent overlay div. I'd like everything behind the div the be blurred, like this:

SFW image

Here is a jsfiddle which doesn't work: http://jsfiddle.net/u2y2091z/

Any ideas how to make this work? I'd like to keep this as uncomplicated as possible and have it be cross-browser. Here is the CSS I'm using:

#overlay {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;

    background:black;
    background:rgba(0,0,0,0.8);

    filter:blur(4px);
    -o-filter:blur(4px);
    -ms-filter:blur(4px);
    -moz-filter:blur(4px);
    -webkit-filter:blur(4px);
}
Swordtail answered 20/12, 2014 at 20:14 Comment(3)
Maybe make the div opaque but use a pseudo element with the image as it's background which can be independently blurred.Norinenorita
@chipChocolate.py CSS filters are supported in FF35+ by default. But I'm agree with you, we as developers shouldn't rely on it as it's not a cross browser feature.Corri
CSS filters are now supported in most major browsers.Fruity
S
66

I was able to piece together information from everyone here and further Googling, and I came up with the following which works in Chrome and Firefox: http://jsfiddle.net/xtbmpcsu/. I'm still working on making this work for IE and Opera.

The key is putting the content inside of the div to which the filter is applied:

body {
    background: #300000;
    background: linear-gradient(45deg, #300000, #000000, #300000, #000000);
    color: white;
}
#mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    opacity: 0.5;
}
img {
    filter: blur(10px);
    -webkit-filter: blur(10px);
    -moz-filter: blur(10px);
  -o-filter: blur(10px);
  -ms-filter: blur(10px);
    position: absolute;
    left: 100px;
    top: 100px;
    height: 300px;
    width: auto;
}
<div id="mask">
    <p>Lorem ipsum ...</p>
    <img src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

So mask has the filters applied. Also, note the use of url() for a filter with an <svg> tag for the value -- that idea came from http://codepen.io/AmeliaBR/pen/xGuBr. If you happen to minify your CSS, you might need to replace any spaces in the SVG filter markup with "%20".

So now, everything inside the mask div is blurred.

Swordtail answered 21/12, 2014 at 19:33 Comment(4)
it's sooo cleverAton
Chrome doesn't like the final filter: url(.... Remove that and Chrome successfully uses filter: blur(10px);.Kraken
Did I misunderstand? It's not what the OP wants. The texts should not be blurred.Immolation
@Eric, you clearly misunderstand, since the answerer is the OP.Taeniasis
K
250

For a more simple and up to date answer:

backdrop-filter: blur(6px);

Note browser support is not perfect but in most cases a blur would be non essential.

Kemeny answered 24/9, 2019 at 15:23 Comment(5)
Note, as of 2021-02-01, no version of Firefox currently supports this feature.Fermanagh
Firefox technically has the support for it, but it is a disabled flag you can enable in about:config.Snap
Example using a position:fixed div overlay: jsfiddle.net/hfjqa6nsHancock
Note, as of 2022-09-08, Firefox has supported this property since July :D giving it a 94% global acceptance rate caniuse.com/css-backdrop-filterArlie
Getting global support of 96.28% today, 2023-12-12.Ptyalism
A
76

Here is an example that uses svg filter.

The idea is to use an svg element with height same as the #overlay and apply the feGaussianblur filter on it. This filter is applied on an svg image element. To give it an extruded effect, you could use a box-shadow at the bottom of the overlay.

Browser Support for svg filters.

Demo on Codepen

body {
  background: #222222;
}
#container {
  position: relative;
  width: 450px;
  margin: 0 auto;
}
img {
  height: 300px;
}
#overlay {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 1;
  color: rgba(130, 130, 130, 0.5);
  font-size: 50px;
  text-align: center;
  line-height: 100px;
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
}
<div id="container">
  <img src="http://lorempixel.com/450/300/sports" />
  <div id="overlay">WET</div>
  <svg width="450" height="100" viewBox="0 0 450 100" style="position: absolute; top: 0;">
    <defs>
      <filter id="blur">
        <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
      </filter>
    </defs>
    <image filter="url(#blur)" xlink:href="http://lorempixel.com/450/300/sports" x="0" y="0" height="300px" width="450px" />
  </svg>
</div>
Aby answered 20/12, 2014 at 21:6 Comment(0)
S
66

I was able to piece together information from everyone here and further Googling, and I came up with the following which works in Chrome and Firefox: http://jsfiddle.net/xtbmpcsu/. I'm still working on making this work for IE and Opera.

The key is putting the content inside of the div to which the filter is applied:

body {
    background: #300000;
    background: linear-gradient(45deg, #300000, #000000, #300000, #000000);
    color: white;
}
#mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    opacity: 0.5;
}
img {
    filter: blur(10px);
    -webkit-filter: blur(10px);
    -moz-filter: blur(10px);
  -o-filter: blur(10px);
  -ms-filter: blur(10px);
    position: absolute;
    left: 100px;
    top: 100px;
    height: 300px;
    width: auto;
}
<div id="mask">
    <p>Lorem ipsum ...</p>
    <img src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

So mask has the filters applied. Also, note the use of url() for a filter with an <svg> tag for the value -- that idea came from http://codepen.io/AmeliaBR/pen/xGuBr. If you happen to minify your CSS, you might need to replace any spaces in the SVG filter markup with "%20".

So now, everything inside the mask div is blurred.

Swordtail answered 21/12, 2014 at 19:33 Comment(4)
it's sooo cleverAton
Chrome doesn't like the final filter: url(.... Remove that and Chrome successfully uses filter: blur(10px);.Kraken
Did I misunderstand? It's not what the OP wants. The texts should not be blurred.Immolation
@Eric, you clearly misunderstand, since the answerer is the OP.Taeniasis
A
26
background: rgba(255,255,255,0.5);
backdrop-filter: blur(5px);

Instead of adding another blur background to your content, you can use backdrop-filter. FYI IE 11 and Firefox may not support it. Check caniuse.

Demo:

header {
  position: fixed;
  width: 100%;
  padding: 10px;
  background: rgba(255,255,255,0.5);
  backdrop-filter: blur(5px);
}
body {
  margin: 0;
}
<header>
  Header
</header>
<div>
  <img src="https://dummyimage.com/600x400/000/fff" />
  <img src="https://dummyimage.com/600x400/000/fff" />
  <img src="https://dummyimage.com/600x400/000/fff" />
</div>
Albumenize answered 11/12, 2019 at 2:17 Comment(3)
The same solution has already been proposed: https://mcmap.net/q/127889/-how-can-i-make-a-css-glass-blur-effect-work-for-an-overlayMassasauga
Is there a way to achieve something similar for an inline SVG!?Danieladaniele
@Danieladaniele check this sitepoint.com/…Albumenize
R
15

If you're looking for a reliable cross-browser approach today, you won't find a great one. The best option you have is to create two images (this could be automated in some environments), and arrange them such that one overlays the other. I've created a simple example below:

<figure class="js">
    <img src="http://i.imgur.com/3oenmve.png" />
    <img src="http://i.imgur.com/3oenmve.png?1" class="blur" />
</figure>
figure.js {
    position: relative;
    width: 250px; height: 250px;
}

figure.js .blur {
    top: 0; left: 0;
    position: absolute;
    clip: rect( 0, 250px, 125px, 0 );
}

Though effective, even this approach isn't necessarily ideal. That being said, it does yield the desired result.

enter image description here

Rabelaisian answered 20/12, 2014 at 21:2 Comment(0)
I
10

Here's a possible solution.

HTML

<img id="source" src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />

<div id="crop">
    <img id="overlay" src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

CSS

#crop {
    overflow: hidden;

    position: absolute;
    left: 100px;
    top: 100px;

    width: 450px;
    height: 150px;
}

#overlay {
    -webkit-filter:blur(4px);
    filter:blur(4px);

    width: 450px;
}

#source {
    height: 300px;
    width: auto;
    position: absolute;
    left: 100px;
    top: 100px;
}

I know the CSS can be simplified and you probably should get rid of the ids. The idea here is to use a div as a cropping container and then apply blur on duplicate of the image. Fiddle

To make this work in Firefox, you would have to use SVG hack.

Idona answered 20/12, 2014 at 20:31 Comment(3)
@chipChocolate.py I guess you need to use the SVG hack in that case then, demosthenes.info/blog/534/Crossbrowser-Image-Blur .Dialectologist
Note that for CSS filter, you could omit vendor prefixes other than -webkit- since it is not implemented in those browsers. It's better to put the standard declaration at the end - after all prefixed versions.Corri
FF is OK, now (54.0.1 (32-bit)). Just perfect! Tx!Pori
S
9

From backdrop-filter

...apply graphical effects such as blurring or color shifting to the area behind an element. Because it applies to everything behind the element, to see the effect you must make the element or its background at least partially transparent.

Shroff answered 7/2, 2021 at 14:14 Comment(1)
Consider the compatibility of the filter as it doesn't work with Firefox desktop & Android versions at the moment.Mychal
S
5

This will do the blur overlay over the content:

.blur {
  display: block;
  bottom: 0;
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
  background-color: rgba(0, 0, 0, 0.5);
}
Seedbed answered 11/7, 2020 at 11:1 Comment(0)
S
4

#bg, #search-bg {
  background-image: url('https://images.pexels.com/photos/719609/pexels-photo-719609.jpeg?w=940&h=650&auto=compress&cs=tinysrgb');
  background-repeat: no-repeat;
  background-size: 1080px auto;
}

#bg {
  background-position: center top;
  padding: 70px 90px 120px 90px;
}

#search-container {
  position: relative;
}

#search-bg {
  /* Absolutely position it, but stretch it to all four corners, then put it just behind #search's z-index */
  position: absolute;
  top: 0px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  z-index: 99;

  /* Pull the background 70px higher to the same place as #bg's */
  background-position: center -70px;

  -webkit-filter: blur(10px);
  filter: url('/media/blur.svg#blur');
  filter: blur(10px);
}

#search {
  /* Put this on top of the blurred layer */
  position: relative;
  z-index: 100;
  padding: 20px;
  background: rgb(34,34,34); /* for IE */
  background: rgba(34,34,34,0.75);
}

@media (max-width: 600px ) {
  #bg { padding: 10px; }
  #search-bg { background-position: center -10px; }
}

#search h2, #search h5, #search h5 a { text-align: center; color: #fefefe; font-weight: normal; }
#search h2 { margin-bottom: 50px }
#search h5 { margin-top: 70px }
<div id="bg">
  <div id="search-container">
    <div id="search-bg"></div>
    <div id="search">
      <h2>Awesome</h2>
      <h5><a href="#">How it works »</a></h5>
    </div>
  </div>
</div>
Sussex answered 26/2, 2018 at 9:7 Comment(0)
D
2

I came up with this solution.

Click to view image of blurry effect

It is kind of a trick which uses an absolutely positioned child div, sets its background image same as the parent div and then uses the background-attachment:fixed CSS property together with the same background properties set on the parent element.

Then you apply filter:blur(10px) (or any value) on the child div.

*{
    margin:0;
    padding:0;
    box-sizing: border-box;
}
.background{
    position: relative;
    width:100%;
    height:100vh;
    background-image:url('https://images.unsplash.com/photo-1547937414-009abc449011?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
    background-size:cover;
    background-position: center;
    background-repeat:no-repeat;
}

.blur{
    position: absolute;
    top:0;
    left:0;
    width:50%;
    height:100%;
    background-image:url('https://images.unsplash.com/photo-1547937414-009abc449011?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
    background-position: center;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-size:cover;
    filter:blur(10px);
    transition:filter .5s ease;
    backface-visibility: hidden;
}

.background:hover .blur{
    filter:blur(0);
}
.text{
    display: inline-block;
    font-family: sans-serif;
    color:white;
    font-weight: 600;
    text-align: center;
    position: relative;
    left:25%;
    top:50%;
    transform:translate(-50%,-50%);
}
<head>
    <title>Blurry Effect</title>
</head>
<body>
    <div class="background">
        <div class="blur"></div>
        <h1 class="text">This is the <br>blurry side</h1>
    </div>
</body>

view on codepen

Dygal answered 5/4, 2019 at 22:0 Comment(0)
S
2

I know my answer is late but here is a better solution to achieve the same effect. This also blurs out text as well and works well on Chrome, Edge, Firefox. To achieve this effect

  1. Use an RBGA color variables with alpha of .8 as a class on the parent div
  2. Apply blur effect on the div
  3. Lastly add some css transition
.myBlur{
   background:rgba(252, 245, 235, .8);
   -webkit-backdrop-filter: blur(4px);
   backdrop-filter: blur(4px);
   transition: background-color .3s cubic-bezier(.42, .00, .58, 1.00);
}

Any object that scrolls under this div will automatically be blured out enter image description here

Speechless answered 12/4, 2023 at 5:42 Comment(1)
Thank you for this additional answer. Mind adding some points on why this is a better solution?Swordtail
F
1

Here's a solution that works with fixed backgrounds, if you have a fixed background and you have some overlayed elements and you need blured backgrounds for them, this solution works:

Image we have this simple HTML:

<body> <!-- or any wrapper -->
   <div class="content">Some Texts</div>
</body>

A fixed background for <body> or the wrapper element:

body {
  background-image: url(http://placeimg.com/640/360/any);
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

And here for example we have a overlayed element with a white transparent background:

.content {
  background-color: rgba(255, 255, 255, 0.3);
  position: relative;
}

Now we need to use the exact same background image of our wrapper for our overlay elements too, i use it as a :before psuedo-class:

.content:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  filter: blur(5px);
  background-image: url(http://placeimg.com/640/360/any);
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

Since the fixed background works in a same way in both wrapper and overlayed elements, we have the background in exactly same scroll position of the overlayed element and we can simply blur it. Here's a working fiddle, tested in Firefox, Chrome, Opera and Edge: https://jsfiddle.net/0vL2rc4d/

NOTE: In firefox there's a bug that makes screen flicker when scrolling and there are fixed blurred backgrounds. if there's any fix, let me know

Flinders answered 7/12, 2019 at 10:31 Comment(0)
N
-1

Idk how i will be useful here, but theres the working fiddle btw https://jsfiddle.net/dqc59tfg/7/

#overlay {
width: 100vw;
height: 100vh;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
backdrop-filter: blur(6px);

background:transparent;
background: transparent;


}
body {
    background: #300000;
    background: linear-gradient(45deg, #300000, #000000, #300000, #000000);
}


img {
    height: 100vh;
    width: 100vw;
    position: absolute;
    left: none;
    top: none;
}
Naylor answered 29/7, 2023 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.