Scrollblur
As a "design freak" I'm always looking for suitable inspiration, and what better way than to drop by the websites of the big agencies every now and then; that's how I occasionally end up on the site of Syzygy. While scrolling I noticed that the header image on the home page gets slowly blurred the further down the page you scroll. I want that too! Pretty nice! Of course it had to be recreated, and it was especially interesting to me because I assumed there is no CSS property for "blur image" (and I was apparently wrong). So instead of Stack Overflowing it first, I went with a different method and briefly present both options here. Maybe someone finds the effect as impressive as I do and can take my code as a guide.
Option 1: Fade
The first approach was to simply stack two images on top of each other and fade one of them out proportionally to the scroll position while scrolling. For that we need the image in two versions: once with a blur effect and once without. I processed the original image in Photoshop with a Gaussian blur and set 8px of blur (you have to experiment a bit with the values depending on the image).
Since I also wanted to build it as a hero image (full width, baby) like on Syzygy, I defined a div with 100% width and position:relative; and set the blurred image as its background-image. Inside that div goes another div with 100% width and 100% height, position:absolute and the "unblurred image" as background-image, so that the unblurred image overlays the blurred one, i.e. the upper div with the unblurred image covers the div with the blurred one. As soon as the user scrolls, we slowly fade out the "inner" div (= unblurred), so the "outer" div (= blurred) fades in. So far, so simple. Only calculating the opacity value could cause a few headaches.
After a bit of experimenting I arrived at the following solution: as soon as the image has been scrolled 100% out of the viewport, we want an opacity of 0 for the inner div, so that the outer div with the blurred image becomes visible. So first we need 1% of the image's height to orient ourselves, which we can calculate with
100 / $('#hero-image-inner').height()
We multiply this value by the scroll position in px (= the number of pixels we've already scrolled down). We subtract this value from 1, since we want a decreasing opacity value (opacity 1 means visible, opacity 0 invisible). Personally I additionally divide the value by 50, since I want 100% blur already at 50%. Otherwise the image would only be "unblurred" (= the inner div has an opacity of 0) once the user has scrolled so far that they can no longer see the image. That would be silly, of course. But as we know, code says more than 1000 words:
Javascript
$(document).on('scroll', function(){
$("#hero-image-inner").css("opacity", 1 - (100 / $('#hero-image-inner').height() * $(document).scrollTop()) / 50);
});
HTML
<div class="hero-image-outer">
<div id="hero-image-inner"></div>
</div>
Option 2: CSS filter
(A video showing the second variant was originally embedded here.)
The second option, which was new to me too, sets the CSS filter "blur" depending on how far the page has already been scrolled. If you haven't worked with it yet, you can get an introduction to CSS filters at W3Schools. With this variant we need no Photoshop or other image editing program, since the effect is generated directly in the browser. The jQuery function is now triggered whenever the page is scrolled and recalculates the "blur filter" each time. The variable percent is calculated differently than above, since the blur filter expects a value of 0-100 and not 0-1. percent is thus calculated from the total height of the image in pixels multiplied by the current scroll position. If we scroll down 2px, for example, the blur value would be exactly 400 for an image size of 200x200. That would be a bit much, since after a single pixel the whole image would be blurred. That's why we only need a fraction of the value, which we get by using a "partial value" (20 in this case) that we divide by the calculated value. If you want a faster or slower animation, just play around a bit with the divisor 20 - a higher value leads to a faster animation, a lower value accordingly to a slower one.
HTML
<img src="images/clearimage.png" id="heroimage">
Javascript
$(document).on('scroll', function(){
var percent = (20 / $('#heroimage').height() * $(document).scrollTop());
$("#heroimage").css("filter", "blur(" + percent + "px)");
$("#heroimage").css("filter", "filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='(" + percent + "')");
});
Very important here: I found the calculation of the opacity / blur value by trial and error. It may not be the most performant or best solution. If someone can offer a "cleaner" solution, they are welcome to let me know in the comments.
TL;DR
- Option 1: overlay two images (blurred & unblurred), fade one out
- Option 2: CSS blur filter
- Calculate the percentage from image height * scroll position