Flying memes

A pure CSS3 coverflow effect for Chrome, Firefox and Safari

I’ve been recently playing with some of the newest CSS3 features, such as pseudoclasses selectors, transition and transform properties and attr(). In order to have something concrete on which test these features¬† I created a coverflow effect that works only out of CSS instructions without the use of javascript.


I used some of the amazing CSS 3D transformations to archieve this effect under WebKit based browsers. Here’s a snippet from the page:

    
  #container{
     margin: 0 auto;
     width: 100%;
     height: 90%;
     max-width: 1024px;
     -webkit-transform-style: preserve-3d;
     -webkit-perspective: 900; 
     -webkit-perspective-origin: 100% 30%;
  }

The container, which is the div that hold the rest of the elements, has some -webkit-* experimental properties that set the position and the distance of the point of view of the user from the scene, as much as it happens with 3D software.

After this each card needs to be rotated against its Y axes; here comes to rescue another CSS3 property:


  .card{
     -webkit-transform: rotateY( 120deg);
  }

Then, all you need is find a way to trigger a change of CSS properties in your .card elements while specifying a transition which handles this change smoothly. So first let’s add this transition:


  .card{
     -webkit-transition: all 1s ease-out;
  }

And then let’s use the :target pseudoclass which gets applied to an <a> element when its name became part of the URL (either because clicked or typed):


  .card:target{
    -webkit-transform: rotateY( 0deg);
  }

The trickiest part is then try to make this thing works also under Firefox which doesn’t have 3D transformations. It turns out that you can emulate them by using wisely the skew(xdeg, ydeg) transform, so you can do the following:


  .card{
     -moz-transform: skew(0deg,-35deg) scale(0.70);
  }
  .card:target{
     -moz-transform: skew(0deg,0deg) scale(1);
  }

Good, but now there’s another challenge: how to solve this ?

The elements on the right side of the selected one have two issues: they should be inclined on the opposite angle and the way they overlap each other should also be reversed.

To solve the first part we can rely on the ~ selector to tell the browser that each element following the selected one must obey to a different skew angle:


  .card:target ~ .card{
    -moz-transform: skew(0deg,20deg) scale(0.70);
  }

The only solution I found to archive the second issue is to use the + selector iteratively in order to assign a z-index to an element based on its distance from the selected one:


  .card:target + .card{
    z-index: 10;
  }

  .card:target + .card + .card{
    z-index: 9;
  }

  .card:target + .card + .card + .card {
    z-index: 8;
  }

  .card:target + .card + .card + .card + .card{
    z-index: 7;
  }

  .card:target + .card + .card + .card + .card + .card{
    z-index: 6;
  }

  .card:target + .card + .card + .card + .card + .card + .card{
    z-index: 5;
  }

  .card:target + .card + .card + .card + .card + .card + .card + .card{
    z-index: 4;
  }

  .card:target + .card + .card + .card + .card + .card + .card + .card + .card{
    z-index: 3;
  }

  .card:target + .card + .card + .card + .card + .card + .card + .card + .card + .card{
    z-index: 2;
  }

  .card:target + .card + .card + .card + .card + .card + .card + .card + .card + .card + .card{
    z-index: 1;
  }

Here’s the final result:

You can have a working demo at this address:
http://sandropaganotti.com/wp-content/goodies/demos/cards/index.html#aela

Tags: , , ,