Code and Stuff

Sep 15, 2012

CSS3 Miniature Effect

Miniature effect

It has been implemented using 6 divs stacked one on top of the other using css. The higher the z-index, the narrower and less blurred it is. The blur is applied using SVG filters.

The six layers are splitting the picture in 13 stripes. The mid one is not blurred.

The original picture is:

The code

Layer 1
Lots of Blur
Layer 2
Little Blur
Layer 3
No Blur
As explained earlier the effect consists of 6 div tags stacked, blurred and sized with css. This layers are enclosed in two more divs. One for the positioning and the outer one to clip and add the border. On the right an example is shown on how the layers are stacked and sized (only 3 layers shown).

Blurring is obtained by applying an SVG filter to the HTML content via the CSS filters. SVG filters can be embedded in the HTML page, but should be without the namespace (not valid XML). For convenience only two of the 5 filters are shown.

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
  <filter id="blur5">
    <feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
  </filter>
  <filter id="blur4">
    <feGaussianBlur in="SourceGraphic" stdDeviation="4"/>
  </filter>
  ...
</svg>
In HTML the 6 layers look like the following:
<div class='border'>
   <div class='positioning'>
      <div class='layer1'></div>
      <div class='layer2'></div>
      <div class='layer3'></div>
      <div class='layer4'></div>
      <div class='layer5'></div>
      <div class='layer6'></div>
   </div>
</div>

The picture used in the example is 447 pixel wide and 325 pixel high. We want the central layer to be of half the hight of the visible part of the other layers. This will give us 13 horizontal slices of the original picture. Each slice is 25 pixel high (325/13).

.positioning > div {
   background: url("https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirUSB_EIev8C1LFSu6D74rhXEy_2o66xjt9FJZmoQqvIyAUomOh0ID8J2zW_3L_yVLlI8ncI6geDspX0bNdI642OzNXbe5oKRzQv6D8VLzPCscAyAfIMm1pgJbJYJYRYJl3COPuyrw27I/s1600/leit.jpg");
   position: absolute;
   width: 447px; /* this is the width of the picture */
   left: 0px;
}

.positioning {
   /* we shift the picture to cut 10px away (see border) */
   margin: -10px; 
   position: relative;
   height: 325px;
   width: 447px;
}

.border {
   /* cut away a 10px border by making div smaller */
   overflow: hidden; 
   height: 305px;
   width: 427px;
}

.layer1 { 
   /* inherited position absolute from .positioning > div */
   z-index:1;
   top: 0px;
   bottom: 0px;
   background-position: 0px -100px;
   filter: url(#blur5);
   -webkit-filter: blur(5px);
}

.layer2 {
   z-index:2;
   top: 25px; bottom: 25px;
   /* align background images */
   background-position: 0px -25px;
   filter: url(#blur4);
   -webkit-filter: blur(4px);
}

.layer3 {
   z-index:3;
   top: 50px; bottom: 50px;
   background-position: 0px -50px;
   filter: url(#blur3);
   -webkit-filter: blur(3px);
}

.layer4 {
   z-index:5;
   top: 75px; bottom: 75px;
   background-position: 0px -75px;
   filter: url(#blur2);
   -webkit-filter: blur(2px);
}

.layer5 {
   z-index:5;
   top: 100px; bottom: 100px;
   background-position: 0px -100px;
   filter: url(#blur1);
   -webkit-filter: blur(1px);
}

.layer6 {
   z-index:6;
   top: 125px; bottom: 125px;
   background-position: 0px -125px;
   /* no blur */
}

And that's it. Not all pictures give a nice result with this effect. It is out of the scope of this post to address the selection of good pictures for the miniature effect.

UPDATE: Single filter implementation that does not need any additional divs (Only firefox)

No comments: