161

It seems Apple's overlay is more than just a transparency. Any ideas on how to achieve this effect with CSS and possibly JS?

More than just transparency

Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
Lumpy
  • 3,632
  • 4
  • 34
  • 58
  • 2
    A more pressing concern in my opinion is how to setup an element that applies a dynamic blur to any object behind it. So if you had an object that could pan and zoom, the element on top would blur dynamically with low performance hit. – Rhodes Sep 03 '13 at 13:57
  • 1
    See also [this question](http://stackoverflow.com/questions/17092299/how-to-use-css-and-javascript-to-create-a-blurred-frosted-background) for a similar problem. – Keith Sep 20 '13 at 11:56
  • 43
    I find it perhaps most worrying that this is wanted as an 'IOS7 feature' while Windows Vista Aero interface has been doing the exact same thing with its window chromes since 2006. – Niels Keurentjes Sep 29 '13 at 11:41
  • 1
    @NielsKeurentjes Heh, a true point. I incorporated the effect into a design a few years ago after being inspired by Windows. However, back then I went for the decidedly simpler route of just baking the effect into the images. http://www.ryanwilliams.co.uk/previews/made2race/1.html – Ryan Williams Nov 04 '13 at 13:42
  • http://geoffreydesigns.com/ios-parallax-effect-with-css/ – Geoffrey Burdett Jul 11 '14 at 20:06

14 Answers14

146

It is possible with CSS3 :

#myDiv {
    -webkit-filter: blur(20px);
    -moz-filter: blur(20px);
    -o-filter: blur(20px);
    -ms-filter: blur(20px);
    filter: blur(20px);
    opacity: 0.4;
}

Example here => jsfiddle

Cana
  • 2,204
  • 1
  • 13
  • 12
  • could I use this on the icons as well? possibly up the transparency? – Lumpy Jun 10 '13 at 23:59
  • It's almost like a multiply effect on the icons. – Lumpy Jun 11 '13 at 00:00
  • I was hoping to use this on a background image. But I guess that's not possible. Only reason I didn't accept your answer – Lumpy Jun 11 '13 at 17:49
  • You can use it with a background image => [jsfiddle](http://jsfiddle.net/SvH6w/1/) – Cana Jun 11 '13 at 22:58
  • 120
    This does not achieve the effect as in iOS7 where an element blurs parts of the background. – Design by Adrian Jun 12 '13 at 08:29
  • 9
    I edited my jsfiddle, now it does the trick like IOS7 ;) => [CSS3 IOS7 effect](http://jsfiddle.net/SvH6w/6/) – Cana Jun 12 '13 at 08:55
  • 34
    As Adrian noted, the filter only blurs an element and it's children. It can't be used for an overlay to blur parent elements or adjacent elements, so the iOS 7 effect is not possible with CSS. – Jason Jun 14 '13 at 23:01
  • 11
    If you think it's just blurring going on to achieve this effect you'd be wrong. I'm working on a simple open sourced repository that achieves this effect using both JS and CSS 3, stay tuned :) – Ryan Brodie Jun 22 '13 at 12:03
  • 5
    This doesn't work in FX - they don't support `-moz-filter: blur()`. Instead you have to use an SVG filter, see my answer for details. – Keith Sep 20 '13 at 13:27
  • i made a fiddle with css-transition. looks nice but performance seems bad: http://jsfiddle.net/SvH6w/1466/ – Benjamin Oct 04 '13 at 16:30
  • 2
    This answer is a little misleading. The linked fiddle suggests the blur is an overlayed element blurring content beneath it, but that's not the case. It uses some clever trickery involving two divs of different height with same background image. Sufficient for its niche use, but absolutely not the same as the iOS7 effect. It also begs a larger question where if you're willing to use overlayed divs with set background images, why not just have the top div's background image be a permanently blurred image and save the processing power... – isick May 07 '14 at 16:31
  • This doesn't blur a part of the original background. – Murhaf Sousli Nov 09 '14 at 03:23
  • @Cana Your solution is not practicable because you cannot scroll over a list in the background and have a ios blur effect of some elements at the top. With your solution you need the background list a second time in the front. This is not applicable or leads to bad performance. – Michael Feb 15 '15 at 19:40
  • @consigliere support for `filter: blur()` was added in Firefox 35, long after this question. – Keith Mar 04 '16 at 07:32
48

You made me want to try, so I did, check out the example here:

http://codepen.io/Edo_B/pen/cLbrt

Using:

  1. HW Accelerated CSS filters
  2. JS for class assigning and arrow key events
  3. Images CSS Clip property

that's it.

I also believe this could be done dynamically for any screen if using canvas to copy the current dom and blurring it.

Edo Ben Shitrit
  • 525
  • 3
  • 5
39

[Edit] In the future (mobile) Safari 9 there will be -webkit-backdrop-filter for exactly this. See this pen I made to showcase it.

I thought about this for the last 4 weeks and came up with this solution.

Live Demo

[Edit] I wrote a more indepth post on CSS-Tricks

This technique is using CSS Regions so the browser support is not the best at this moment. (http://caniuse.com/#feat=css-regions)

The key part of this technique is to split apart content from layout by using CSS Region. First define a .content element with flow-into:content and then use the appropriate structure to blur the header.

The layout structure:

<div class="phone">
 <div class="phone__display">
  <div class="header">
    <div class="header__text">Header</div>
    <div class="header__background"></div>
  </div>
  <div class="phone__content">
  </div>
 </div>
</div>

The two important parts of this layout are .header__background and .phone__content - these are the containers where the content should flow though.

Using CSS Regions it is simple as flow-from:content (.content is flowing into the named region content)

Now comes the tricky part. We want to always flow the content through the .header__background because that is the section where the content will be blured. (using webkit-filter:blur(10px);)

This is done by transfrom:translateY(-$HeightOfTheHeader) the .content to ensure that the content will always flow though the .header__background. This transform while always hide some content beneath the header. Fixing this is ease adding

.header__background:before{
  display:inline-block;
  content:'';
  height:$HeightOfTheHEader
}

to accommodate for the transform.

This is currently working in:

  • Chrome 29+ (enable 'experimental-webkit-features'/'enable-experimental-web-platform-features')
  • Safari 6.1 Seed 6
  • iOS7 (slow and no scrolling)
FWeinb
  • 391
  • 4
  • 5
16

This is sort of possible with FireFox now thanks to the element style attribute.

This experimental attribute lets you use any HTML content as a background image. So, to create the background you need three overlays:

  1. Simple overlay with a solid background (to hide the real overlay content).
  2. Overlay with a -moz-element background that sets the content. Note that FX doesn't support the filter: blur() attribute, so we need to us an SVG.
  3. Overlay with non blurred content.

So, put together:

SVG blur filter (works in FX, other browsers could use filter:blur()):

<svg>
  <defs>
    <filter id="svgBlur">
      <feGaussianBlur stdDeviation="10"/>
    </filter>
  </defs>
</svg>

CSS blur style:

.behind-blur 
{
    filter         : url(#svgBlur); 
    opacity: .4;
    background: -moz-element(#content);
    background-repeat: no-repeat;
}

Finally 3 layers:

<div class="header" style="background-color: #fff">&nbsp;</div>
<div class="header behind-blur">&nbsp;</div>
<div class="header">
    Header Text, content blurs behind
</div>

Then to move this around just set the background-position (sample in jQuery but you could use anything):

$('.behind-blur').css({
    'background-position': '-' + left + 'px -' + top + 'px'
}); 

Here it is as a JS Fiddle, FX only.

Keith
  • 150,284
  • 78
  • 298
  • 434
  • 1
    Your solution is similar to the one I had in mind. I fixed the glitch (http://jsfiddle.net/RgBzH/30/) by extending the slice of the background blurred, so the blur actually happens on real content, not the sliced one. Good execution, anyway. – Pier Paolo Ramon Sep 24 '13 at 10:58
  • @PierPaoloRamon nice tweak - it I was going to use this I'd probably extend the SVG filter a bit to include the increased brightness/reduced contrast that iOS7 does too, but FX only means strictly sandbox at this point. I've asked [another question](http://stackoverflow.com/questions/18919305/equivalent-for-moz-element-in-other-browsers) about workarounds. – Keith Sep 24 '13 at 12:51
  • BTW, your solution just brings ios7-like blur to Firefox OS, and that's neat (I have to test that). – Pier Paolo Ramon Sep 24 '13 at 13:02
14

Check out this demo page.
This demo uses html2canvas for rendering document as an image.

http://blurpopup.labs.daum.net/

  1. When the "Show popup" link is clicked, the 'makePopup' function is called.
  2. 'makePopup' runs html2canvas for rendering document as an image.
  3. The image is converted to data-url string and it is painted as the popup's background-image.
  4. Popup's bg is blurred by -webkit-filter:blur
  5. Append the popup into document.
  6. While you're dragging the popup, it changes its own background-position.
Gyutae Jo
  • 167
  • 1
  • 3
10

This pen I found the other day seemed to do it beautifully, just a bit of css and 21 lines of javascript. I hadn't heard of the cloneNode js command until I found this, but it totally worked for what I needed for sure.

http://codepen.io/rikschennink/pen/zvcgx

Detail: A. Basically it looks at your content div and invokes a cloneNode on it so it creates a duplicate which it then places inside the overflow:hidden header object sitting on top of the page. B. Then it simply listens for scrolling so that both images seem to match and blurs the header image... annnnd BAM. Effect achieved.

Not really fully do-able in CSS until they get the lil bit of scriptability built into the language.

Lux.Capacitor
  • 336
  • 3
  • 12
  • Looks great! Although this obviously wouldn't work too well with dynamic content, unless you update the duplicate every time anything changes - which would probably be a big performance hit. – Nass Mar 27 '14 at 16:47
  • I suppose, but not really sure where you would be changing the images out and trying to do this effect? If done properly it shouldn't be a big hit at all if you recycle the clone. Perhaps you can detail a case converse to this? Say for example you make an image feed and want to have some menu options come up with this effect for an image menu for each item...run this as you reveal the panel and the panel that overlays would then look like the poster wanted. Add a wee recycler so dom doesn't endlessly duplicate images every time you open menus and it should perform nicely. – Lux.Capacitor Aug 20 '14 at 18:12
5
  • clone the element you want to blur
  • append it to the element you want to be on top (the frosted window)
  • blur cloned element with webkit-filter
  • make sure cloned element is positioned absolute
  • when scrolling the original element's parent, catch scrollTop and scrollLeft
  • using requestAnimationFrame, now set the webkit-transform dynamically to translate3d with x and y values to scrollTop and scrollLeft

Example is here:

  • make sure to open in webkit-browser
  • scroll inside phone view (best with apple mouse...)
  • see blurring footer in action

http://versie1.com/TEST/ios7/

4

made a quick demo yesterday that actually does what your talking about. http://bit.ly/10clOM9 this demo does the parallax based on the accelerometer so it works best on an iPhone itself. I basically just copy the content we are overlaying into a fixed position element that gets blurred.

note: swipe up to see the panel.

(i used horrible css id's but you get the idea)

#frost{
 position: fixed; 
 bottom: 0; 
 left:0; 
 width: 100%; 
 height: 100px; 
 overflow: hidden;
 -webkit-transition: all .5s;
}
#background2{
 -webkit-filter: blur(15px) brightness(.2);
}

#content2fixed{
 position: fixed;
 bottom: 9px;
 left: 9px;
 -webkit-filter: blur(10px);
}
ericjbasti
  • 2,085
  • 17
  • 19
3

Am not very sure about that, I believe that CSS isn't capable of doing this at the moment

However Chris Coyier has blogged about an old technique with multiple images to achieve such effect, http://css-tricks.com/blurry-background-effect/

Zyad Sherif
  • 933
  • 9
  • 22
  • snapshot of the screen to canvas might work and 'lock' the icons and background together before doing this, but I wasn't able to see if the background still had the parallax effect under the icons when it was blurred... if it didn't, then the minute you start moving the control panel (transparent overlay) the device creates an image of the screen and performs this trickery overtop. mind you, they aren't just limited by web-based things like canvas when doing this since it is at the os level, and may not be limited to webkit stuff. – nosarious Jun 11 '13 at 14:56
3

Check this one out http://codepen.io/GianlucaGuarini/pen/Hzrhf Seems like it does the effect without duplication the background image of the element under itself. See texts are blurring also in the example.

Vague.js

var vague = $blurred.find('iframe').Vague({
  intensity:5 //blur intensity
});
vague.blur();
3

Good News

As of today 11th April 2020, this is easily possible with backdrop-filter CSS property which is now a stable feature in Chrome, Safari & Edge.

I wanted this in our Hybrid mobile app so also available in Android/Chrome Webview & Safari WebView.

  1. https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter
  2. https://caniuse.com/#search=backdrop-filter

Code Example:

Simply add the CSS property:

.my-class {
    backdrop-filter: blur(30px);
    background: transparent;     // Make sure there is not backgorund
}

UI Example 1

See it working in this pen or try the demo:

#main-wrapper {
  width: 300px;
  height: 300px;
  background: url("https://i.picsum.photos/id/1001/500/500.jpg") no-repeat center;
  background-size: cover;
  position: relative;
  overflow: hidden;
}

.my-effect {
  position: absolute;
  top: 300px;
  left: 0;
  width: 100%;
  height: 100%;
  font-size: 22px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: black;
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
  transition: top 700ms;
}

#main-wrapper:hover .my-effect {
  top: 0;
}
<h4>Hover over the image to see the effect</h4>

<div id="main-wrapper">
  <div class="my-effect">
    Glossy effect worked!
  </div>
</div>

UI Example 2

Let's take an example of McDonald's app because it's quite colourful. I took its screenshot and added as the background in the body of my app.

I wanted to show a text on top of it with the glossy effect. Using backdrop-filter: blur(20px); on the overlay above it, I was able to see this:

Main screenshot enter image description here

Shashank Agrawal
  • 25,161
  • 11
  • 89
  • 121
  • `backdrop-filter` still doesn't work automatically in Firefox though. I doubt that users will turn on the options to activate `backdrop-filter` deliberately just to see this effect. – Richard May 05 '20 at 04:50
0

I've been using svg filters to achieve similar effects for sprites

<svg id="gray_calendar" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 48 48 48">
  <filter id="greyscale">
    <feColorMatrix type="saturate" values="0"/>
  </filter>
  <image width="48" height="10224" xlink:href="tango48i.png" filter="url(#greyscale)"/>
</svg>
  • The viewBox attribute will select just the portion of your included image that you want.
  • Just change the filter to any that you want, such as Keith's <feGaussianBlur stdDeviation="10"/> example.
  • Use the <image ...> tag to apply it to any image or even use multiple images.
  • You can build this up with js and use it as an image or use the id in your css.
technosaurus
  • 7,676
  • 1
  • 30
  • 52
  • Do you happen to have a working example of this somewhere? Perhaps a jsFiddle or similar? Thanks – Blaker Nov 07 '13 at 08:58
0

This might help you!!

This Dynamically changes the background just IOS does

.myBox {
  width: 750px;
  height: 500px;
  border: rgba(0, 0, 0, 0.5) 1px solid;
  background-color: #ffffff;
}

.blurBg {
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index: 0;
}

.blurBg img {
  -webkit-filter: blur(50px);
  margin-top: -150px;
  margin-left: -150px;
  width: 150%;
  opacity: 0.6;
}
Andrew Bone
  • 7,092
  • 2
  • 18
  • 33
-1

Here is my take on this with jQuery. Solution isn't universal, meaning one would have to tweak some of the positions and stuff depending on the actual design.

Basically what I did is: on trigger clone/remove the whole background (what should be blurred) to a container with unblurred content (which, optionally, has hidden overflow if it is not full width) and position it correctly. Caveat is that on window resize blurred div will mismatch the original in terms of position, but this could be solved with some on window resize function (honestly I couldn't be bothered with that now).

I would really appreciate your opinion on this solution!

Thanks

Here is the fiddle, not tested in IE.

HTML

<div class="slide-up">
<div class="slide-wrapper">
    <div class="slide-background"></div>
    <div class="blured"></div>
    <div class="slide-content">
         <h2>Pop up title</h2>

        <p>Pretty neat!</p>
    </div>
</div>
</div>
<div class="wrapper">
<div class="content">
     <h1>Some title</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque molestie magna elit, quis pulvinar lectus gravida sit amet. Phasellus lacinia massa et metus blandit fermentum. Cras euismod gravida scelerisque. Fusce molestie ligula diam, non porta ipsum faucibus sed. Nam interdum dui at fringilla laoreet. Donec sit amet est eu eros suscipit commodo eget vitae velit.</p>
</div> <a class="trigger" href="#">trigger slide</a>

</div>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<filter id="blur">
    <feGaussianBlur stdDeviation="3" />
</filter>
</svg>

CSS

body {
margin: 0;
padding: 0;
font-family:'Verdana', sans-serif;
color: #fff;
}
.wrapper {
position: relative;
height: 100%;
overflow: hidden;
z-index: 100;
background: #CD535B;
}
img {
width: 100%;
height: auto;
}
.blured {
top: 0;
height: 0;
-webkit-filter: blur(3px);
-moz-filter: blur(3px);
-ms-filter: blur(3px);
filter: blur(3px);
filter: url(#blur);
filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='3');
position: absolute;
z-index: 1000;
}
.blured .wrapper {
position: absolute;
width: inherit;
}
.content {
width: 300px;
margin: 0 auto;
}
.slide-up {
top:10px;
position: absolute;
width: 100%;
z-index: 2000;
display: none;
height: auto;
overflow: hidden;
}
.slide-wrapper {
width: 200px;
margin: 0 auto;
position: relative;
border: 1px solid #fff;
overflow: hidden;
}
.slide-content {
z-index: 2222;
position: relative;
text-align: center;
color: #333333;
}
.slide-background {
position: absolute;
top: 0;
width: 100%;
height: 100%;
background-color: #fff;
z-index: 1500;
opacity: 0.5;
}

jQuery

// first just grab some pixels we will use to correctly position the blured element
var height = $('.slide-up').outerHeight();
var slide_top = parseInt($('.slide-up').css('top'), 10);
$wrapper_width = $('body > .wrapper').css("width");
$('.blured').css("width", $wrapper_width);

$('.trigger').click(function () {
    if ($(this).hasClass('triggered')) { // sliding up
        $('.blured').animate({
            height: '0px',
            background: background
        }, 1000, function () {
            $('.blured .wrapper').remove();
        });
        $('.slide-up').slideUp(700);
        $(this).removeClass('triggered');
    } else { // sliding down
        $('.wrapper').clone().appendTo('.blured');
        $('.slide-up').slideDown(1000);
        $offset = $('.slide-wrapper').offset();
        $('.blured').animate({
            height: $offset.top + height + slide_top + 'px'
        }, 700);
        $('.blured .wrapper').animate({
            left: -$offset.left,
            top: -$offset.top
        }, 100);
        $(this).addClass('triggered');
    }
});
Bojana Šekeljić
  • 1,056
  • 1
  • 12
  • 30