[html] How can I make a CSS glass/blur effect work for an overlay?

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);
}

This question is related to html css blur css-filters

The answer is


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.


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

_x000D_
_x000D_
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);
}
_x000D_
<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>
_x000D_
_x000D_
_x000D_


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


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:

_x000D_
_x000D_
header {_x000D_
  position: fixed;_x000D_
  width: 100%;_x000D_
  padding: 10px;_x000D_
  background: rgba(255,255,255,0.5);_x000D_
  backdrop-filter: blur(5px);_x000D_
}_x000D_
body {_x000D_
  margin: 0;_x000D_
}
_x000D_
<header>_x000D_
  Header_x000D_
</header>_x000D_
<div>_x000D_
  <img src="https://dummyimage.com/600x400/000/fff" />_x000D_
  <img src="https://dummyimage.com/600x400/000/fff" />_x000D_
  <img src="https://dummyimage.com/600x400/000/fff" />_x000D_
</div>
_x000D_
_x000D_
_x000D_


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);
}

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.


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.

_x000D_
_x000D_
*{
    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%);
}
_x000D_
<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>
_x000D_
_x000D_
_x000D_

view on codepen


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.


_x000D_
_x000D_
#bg, #search-bg {_x000D_
  background-image: url('https://images.pexels.com/photos/719609/pexels-photo-719609.jpeg?w=940&h=650&auto=compress&cs=tinysrgb');_x000D_
  background-repeat: no-repeat;_x000D_
  background-size: 1080px auto;_x000D_
}_x000D_
_x000D_
#bg {_x000D_
  background-position: center top;_x000D_
  padding: 70px 90px 120px 90px;_x000D_
}_x000D_
_x000D_
#search-container {_x000D_
  position: relative;_x000D_
}_x000D_
_x000D_
#search-bg {_x000D_
  /* Absolutely position it, but stretch it to all four corners, then put it just behind #search's z-index */_x000D_
  position: absolute;_x000D_
  top: 0px;_x000D_
  right: 0px;_x000D_
  bottom: 0px;_x000D_
  left: 0px;_x000D_
  z-index: 99;_x000D_
_x000D_
  /* Pull the background 70px higher to the same place as #bg's */_x000D_
  background-position: center -70px;_x000D_
_x000D_
  -webkit-filter: blur(10px);_x000D_
  filter: url('/media/blur.svg#blur');_x000D_
  filter: blur(10px);_x000D_
}_x000D_
_x000D_
#search {_x000D_
  /* Put this on top of the blurred layer */_x000D_
  position: relative;_x000D_
  z-index: 100;_x000D_
  padding: 20px;_x000D_
  background: rgb(34,34,34); /* for IE */_x000D_
  background: rgba(34,34,34,0.75);_x000D_
}_x000D_
_x000D_
@media (max-width: 600px ) {_x000D_
  #bg { padding: 10px; }_x000D_
  #search-bg { background-position: center -10px; }_x000D_
}_x000D_
_x000D_
#search h2, #search h5, #search h5 a { text-align: center; color: #fefefe; font-weight: normal; }_x000D_
#search h2 { margin-bottom: 50px }_x000D_
#search h5 { margin-top: 70px }
_x000D_
<div id="bg">_x000D_
  <div id="search-container">_x000D_
    <div id="search-bg"></div>_x000D_
    <div id="search">_x000D_
      <h2>Awesome</h2>_x000D_
      <h5><a href="#">How it works ยป</a></h5>_x000D_
    </div>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


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


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to blur

How can I make a CSS glass/blur effect work for an overlay? Can you blur the content beneath/behind a div? CSS blur on background image but not on content iOS 7's blurred overlay effect using CSS? Blur effect on a div element

Examples related to css-filters

How can I make a CSS glass/blur effect work for an overlay? CSS filter: make color image with transparency white How to apply a CSS filter to a background image