Stuff & Nonsense. Website designers in North Wales

M M M Madness

While I was preparing the slides from my full day CSS3 For Responsive Web Design at Smashing Magazine, I got very excited by the new filters in CSS. (313 onwards in my slide deck.) These filters — not to be confused with those legacy, proprietary Microsoft filters — are now well on their way to becoming part of a standard.

I’m also sketching out ideas for a new Stuff and Nonsense site header for launch in October and I thought now would be a good time to get familiar with using filters, perhaps to create something with a little more ‘depth’ than our previous designs, perhaps even something that could animated or respond to mouse movements (or touch.)

Playing around with our current header, I added a blur filter to the madness header division.

.madness {
-webkit-filter : blur(5px);
filter : blur(5px); }

Then i notice that the filter effect inherits to child elements.

The header’s made up of a <header> element, wrapper <div> to group (and help centre) the nutty boys and then the characters themselves, cheekily spelling the word Madness.

<header class="madness">
<div>
<span class="madness__m">M</span>
<span class="madness__a">a</span>
<span class="madness__d">d</span>
<span class="madness__n">n</span>
<span class="madness__e">e</span>
<span class="madness__s">s</span>
<span class="madness__s2">s</span>
</div>
</header>

I didn’t think ‘un-blurring’ the nutty boys would be a problem:

.madness {
-webkit-filter : blur(0);
filter : blur(0); }

or,

.madness {
-webkit-filter : none;
filter : none; }

Silly me.

Turns out there’s no way to un-filter a child element. (Who thought that was a good idea? Honestly?)

I wanted to blur the background and not the nutty boys so I had to use some CSS generated content gymnastics to accomplish that.

First up, turn the header into a positioning context:

.madness {
position : relative; }

Add a pseudo element using :before. Pseudo elements (:before and :after) are placed inside their parent element and can be positioned the same as any (real) element. Stretch out that pseudo element so that it covers its parent completely.

.madness:before {
content : "";
position : absolute;
top : 0;
right : 0;
left : 0;
bottom : 0; }

Now add the street background image to that pseudo element and blur it:

.madness:before {
background: transparent url(banner-madness-lg.png) repeat-x -20% 0;
-webkit-filter : blur(5px);
filter : blur(5px); }

Almost.

The blur effect makes for some nuttiness around the edges of the image, so reset the pseudo element’s position so that it extends outside of its parent.

.madness:before {
top : -10px;
right : -10px;
left : -10px;
bottom : -10px; }

Much better.

I thought it would be fun to move the blurred background while it was moving, so I added an animation:

@-webkit-keyframes slide {
from { background-position : 0 0; } 
to { background-position : -10000px 0; }
}

@keyframes slide {
from { background-position : 0 0; }
to { background-position : -10000px 0; }
}

.madness:before {
background-position : 0 0;
-webkit-animation : slide 600s linear infinite;
-moz-animation : slide 600s linear infinite;
-ms-animation : slide 600s linear infinite;
-o-animation : slide 600s linear infinite;
animation : slide 600s linear infinite; }

While the animation and blur effect combined looked great, performance was terrible. The animation was jerky and scrolling the page become incredibly laggy.

David Yarham on Twitter suggested a 3D transformation with zero values might help.

.madness:before {
-webkit-transform : translate3d(0,0,0);
transform : translate3d(0,0,0); }

I’m still not sure why this works, but I’m not complaining.

Here’s everything wrapped into a nutty demo. You’ll need Chrome to see the effects.

So a few takeaways from this little experiment:

  • Generated content is incredibly useful
  • Filter inheritance can be a pain
  • Not having the ability to override inherited filters is, you guessed it, madness