Image Blur Texture
Click the images below and watch the background change.
Here's a neat little trick you can use to spice up a design. The background image you see above is actually a smaller square image, stretched out and blurred to create a nice texture. Nifty, ain't it? It's so hot that we're using it in the header of the new Forrst. There are two ways to implement it, and they're both relatively painless. Let's get started!
With CSS Filters
The easiest way to create this effect is with a CSS filter. Unfortunately, this method isn't the most compatible with browsers. CSS filters currently only work in newer Webkit browsers, including Chrome, Safari 6 and Opera 15.
CSS filters can be applied to any HTML element, but in this case we’ll just be applying it to an image. The markup will look like this:
<div class="hero"> <img class="hero__background" src="image.jpg"> <h1 class="hero__title">Image Blur</h1> </div>
Note that the image is its own element, not a background image of the container. We can’t selectively blur parts of an element, so the background image will go in its own image tag.
The CSS looks like this:
.hero { position: relative; width: 100%; padding: 2em 0; overflow: hidden; // Hide overflow to contain the background } .hero__background { position: absolute; top: -50%; left: 0; width: 200%; // Where the magic happens -webkit-filter: blur(100px); -webkit-transform: translate3d(0, 0, 0); } .hero__title { position: relative; text-align: center; font-size: 5em; color: white; }
You’ll notice two special CSS properties are being used. The first is -webkit-filter
, which gets us access to the blur function. Other filter functions include hue-rotate, greyscale and sepia.
But what's the second property for? We’ve added a transform effect that does nothing. What this property does is force the user’s browser to hardware accelerate any special effects applied to the element. If you try blurring an element without this second property applied, you’ll see a general drop in frame rate, especially when the page scrolls. Applying a transform, even a “blank” one like this, informs the browser that this element needs special treatment. Hardware-accelerated effects are offloaded to the device’s GPU, which is better equipped to handle the complex math needed for transforms, transitions and filters.
So, this implementation of the blur effect basically only requires two lines of code. Easy! But as we’ve said, not widely supported. Thankfully, there’s another way.
With Canvas
Canvas has much wider browser support (IE9 even!) and allows for many of the same image manipulation tricks as CSS. What we’ll be doing is drawing our image to the canvas, stretching it out, and then blurring its contents.
But first, a quick note about canvas sizing. A canvas always has a fixed-pixel size, which is generally defined on the element itself with the width and height attributes, or in JavaScript with similarly named properties. We want our canvas to stretch the width and height of our hero unit, which we can do very easily in CSS with width: 100%
and height: 100%
. To make most things on the web responsive, you don't have to define pixel value. Canvas, on the other hand, will stretch, but not really, as it will always keep the dimmensions first assigned to it. So a Canvas element that looks like this...
<canvas width="100" height="100">
...will always think it's 100px wide and 100px tall, no matter how far we stretch it in the CSS. It's a quirk that works to our advantage here. There are ways using JavaScript to dynamically change a canvas’s pixel width and height in response to the browser being resized, but we don’t need any of that.
Here’s the markup for our canvas implementation:
<div class="hero"> <canvas class="hero__background" width="200" height="200" id="heroCanvas"></canvas> <h1 class="hero__title">Image Blur Thing</h1> </div>
Here’s the CSS:
// This is our container .hero { position: relative; width: 100%; padding: 2em 0; } // This is our canvas .hero__background { // This stretches the canvas across the entire hero unit position: absolute; top: 0; left: 0; width: 100%; height: 100%; // This positions the canvas under the text z-index: 1; } // This is our title to go over the canvas .hero__title { // This positions the text on top of the canvas position: relative; z-index: 2; // This is just stylistic text-align: center; font-size: 5em; color: white; }
Now for the JavaScript. We’ll start by creating variables referencing our canvas and its drawing context, a separate object that allows us to draw on the canvas.
var canvas = document.getElementById("heroCanvas"); var canvasContext = canvas.getContext("2d");
We’ll also grab an image file and load it within the JavaScript.
var canvasBackground = new Image(); canvasBackground.src = "image.jpg";
Next we’ll write the actual image blur function. StackBlur is doing the heavy lifting here. Shout out to Mario Klingemann, who wrote the swank gaussian blur algorithm for canvas that we're using here.
var drawBlur = function() { // Store the width and height of the canvas for below var w = canvas.width; var h = canvas.height; // This draws the image we just loaded to our canvas canvasContext.drawImage(canvasBackground, 0, 0, w, h); // This blurs the contents of the entire canvas stackBlurCanvasRGBA("heroCanvas", 0, 0, w, h, 100); }
Finally, we’ll add an “onload” event listener to the image we defined earlier, and call our drawBlur function within there. If we load the image and immediately call the blurring function on the next line, the function will most likely run before the image is done loading—and then nothing will happen.
canvasBackground.onload = function() { drawBlur(); }
There’s one main drawback to this method, which you may or may not run across depending on your situation. Canvas will not read images served from another domain, unless the image file includes an Access header allowing for cross-origin resource sharing.
We encountered this problem on an upcoming project. Our images were being served by AWS, which by default doesn’t allow for cross-origin resource sharing. Each image file would need to be given a header allowing other domains to access it.
Try it Yourself
We've created a CodePen with all the HTML, CSS, and JavaScript needed to implement the Canvas method. Try changing the value of the BLUR_RADIUS
variable in the JS to adjust the intensity of the blur.
See the Pen Blurred Image Background by Geoff Kimball (@gakimball) on CodePen.