48

I want an Vista/7-aero-glass-style effect on a popup on my site, and it needs to be dynamic. I'm fine with this not being a cross-browser effect as long as the site still works on all modern browsers.

My first attempt was to use something like

#dialog_base {
  background:white;
  background:rgba(255,255,255,0.8);

  filter:blur(4px);
  -o-filter:blur(4px);
  -ms-filter:blur(4px);
  -moz-filter:blur(4px);
  -webkit-filter:blur(4px);
}

However, as I should have expected, this resulted in the content of the dialog being blurred and the background staying clear. Is there any way to use CSS to blur the background of a semitransparent element instead of its contents?

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
Ky -
  • 30,724
  • 51
  • 192
  • 308

6 Answers6

34

OCT. 2016 UPDATE

Since the -moz-element() property doesn't seem to be widely supported by other browsers except to FF, there's an even easier technique to apply blurring without affecting the contents of the container. The use of pseudoelements is ideal in this case in combination with svg blur filter.

Check the demo using pseudo-element

(Demo was tested in FF v49, Chrome v53, Opera 40 - IE doesn't seem to support blur either with css or svg filter)


The only way (so far) of having a blur effect in the background without js plugins, is the use of -moz-element() property in combination with the svg blur filter. With -moz-element() you can define an element as a background image of another element. Then you apply the svg blur filter. OPTIONAL: You can utilize some jQuery for scrolling if your background is in fixed position.

See my demo here

I understand it is a quite complicated solution and limited to FF (element() applies only to Mozilla at the moment with -moz-element() property) but at least there's been some effort in the past to implement in webkit browsers and hopefully it will be implemented in the future.

otinanai
  • 3,987
  • 3
  • 25
  • 43
  • I've just tried this in Chrome and it seems to be working for me. – cjm2671 Jun 07 '13 at 09:21
  • 7
    The only truly cross-browser blur I've found is Stackblur: http://quasimondo.com/StackBlurForCanvas/StackBlurDemo.html – Imperative Dec 13 '13 at 08:34
  • @Imperative That's really cool, but how can it work with my setup? – Ky - Jun 08 '15 at 16:27
  • @Supuhstar I'd have to know more about your setup. That blur is using HTML5's canvas element. More recently, I just let Compass handle the cross browser CSS - http://compass-style.org/reference/compass/css3/filter/ – Imperative Jun 09 '15 at 18:51
  • @Imperative my setup is described in the question. I don't think a canvas can be used as a CSS background... Or reliably add any sort of background to an element, or to blur existing page content. – Ky - Jun 09 '15 at 20:13
  • 1
    @supuhstar My bad, I didn't realize you were the OP until after I typed that. I'll update my 2013 comment and suggest you have a look at http://blurjs.com/ – Imperative Jun 09 '15 at 21:04
28

In recent versions of major browsers you can use backdrop-filter property.

HTML

<div>backdrop blur</div>

CSS

div {
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}

or if you need different background color for browsers without support:

div {
    background-color: rgba(255, 255, 255, 0.9);
}

@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) {
    div {
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
        background-color: rgba(255, 255, 255, 0.5);  
    }
}

Demo: JSFiddle

Docs: Mozilla Developer: backdrop-filter

Is it for me?: CanIUse

hovado
  • 4,474
  • 1
  • 24
  • 30
17

You can use a pseudo-element to position as the background of the content with the same image as the background, but blurred with the new CSS3 filter.

You can see it in action here: http://codepen.io/jiserra/pen/JzKpx

I made that for customizing a select, but I added the blur background effect.

  • Promising, but it doesn't quite work as expected: http://codepen.io/anon/pen/bmxad – Ky - Sep 04 '13 at 12:41
  • Of course, you have to make some modifications. If you move the div, you have to move the background-position of the div: http://codepen.io/jiserra/pen/JzKpx – Juan Ignacio Serra Sep 04 '13 at 15:52
  • Does this work when background content is text? This will be used for a popup dialog on a site with very few images. – Ky - Sep 09 '13 at 14:58
  • Specifically, the CSS rule is -webkit-filter: blur(4px); -moz-filter: blur(4px); filter: blur(4px); – mikemaccana Oct 20 '13 at 20:43
  • strangely the hack you are using does not seem to work when using a normal div instead of the `content: ''` – Toskan Jan 18 '15 at 00:30
8

There is a simple and very common technique by using 2 background images: a crisp and a blurry one. You set the crisp image as a background for the body and the blurry one as a background image for your container. The blurry image must be set to fixed positioning and the alignment is 100% perfect. I used it before and it works.

body {
    background: url(yourCrispImage.jpg) no-repeat;
}

#container {
    background: url(yourBlurryImage.jpg) no-repeat fixed;
}

You can see a working example at the following fiddle: http://jsfiddle.net/jTUjT/5/. Try to resize the browser and see that the alignment never fails.


If only CSS element() was supported by other browsers other than Mozilla's -moz-element() you could create great effects. See this demo with Mozilla.

otinanai
  • 3,987
  • 3
  • 25
  • 43
  • The problem is that this doesn't work when there's dynamic textual content behind the dialog. I know of this trick, as I've seen it used on http://e926.net – Ky - Jan 28 '13 at 18:48
  • There's also an experimental approach to blur everything behind the dialog but it only works in mozilla with the `-moz-element()` property. Basically, you define an element as a background of another element. Then you can use the svg `feGaussianBlur` filter to blur the background fill. You can see a live demo I've made: http://jsfiddle.net/2VzgL/ . However, the `element()` property is only available in mozilla and no other browser supports it yet. My hint for cross-browser compatibility would be the use of js libraries and customize them as needed, like Pixastic. – otinanai Jan 29 '13 at 15:56
  • 1
    Seems promising, but your jsFiddle doesn't behave predictably when scrolling – Ky - Jan 29 '13 at 16:03
  • 3
    The previous jsFiddle was just an example for the `-moz-element()` property. To behave as expected when scrolling it needs a slightly different implementation and some use of jQuery. Have a look here: http://jsfiddle.net/YgHA8/1/ – otinanai Jan 30 '13 at 15:26
  • True, but you can make a webpage without JavaScript. – Ky - Jan 31 '13 at 23:58
  • Can you submit that last fiddle as an answer? I'll accept it, as it's the most promising solution for now. – Ky - May 05 '13 at 18:26
1

Use an empty element sized for the content as the background, and position the content over the blurred element.

#dialog_base{
  background:white;
  background:rgba(255,255,255,0.8);

  position: absolute;
  top: 40%;
  left: 50%;
  z-index: 50;
  margin-left: -200px;
  height: 200px;
  width: 400px;

  filter:blur(4px);
  -o-filter:blur(4px);
  -ms-filter:blur(4px);
  -moz-filter:blur(4px);
  -webkit-filter:blur(4px);
}

#dialog_content{
  background: transparent;
  position: absolute;
  top: 40%;
  left: 50%;
  margin-left -200px;
  overflow: hidden;
  z-index: 51;
}

The background element can be inside of the content element, but not the other way around.

<div id='dialog_base'></div>
<div id='dialog_content'>
    Some Content
    <!-- Alternatively with z-index: <div id='dialog_base'></div> -->
</div>

This is not easy if the content is not always consistently sized, but it works.

Devon
  • 21
  • 1
1

In which way do you want it dynamic? If you want the popup to successfully map to the background, you need to create two backgrounds. It requires both the use of element() or -moz-element() and a filter (for Firefox, use a SVG filter like filter: url(#svgBlur) since Firefox does not support -moz-filter: blur() as yet?). It only works in Firefox at the time of writing.

See demo here.

I still need to create a simple demo to show how it is done. You're welcome to view the source.