So last time we figured out how to make a div flip using CSS3 animations, but we still have to make our flipping countdown clock look like the number is folding in half. This is going to require some additional CSS. First, let’s set up our HTML.
<div class="wrap"> <ul id="initial"> <li class="first"> <a class="derp"> <div class="flipthis"> <div class="digit">1</div> </div> <div class="flipthis-down"> <div class="digit">1</div> </div> </a> </li> <li class="second"> <a class="derp"> <div class="flipthis2"> <div class="digit">2</div> </div> <div class="flipthis2-down"> <div class="digit">2</div> </div> </a> </li> </ul> </div>
It’s not the prettiest, but it’ll work for our testing purposes. We’ll fix it up when we get into building the final clock. I’ll explain the HTML as we go through the CSS to set it up.
First we’ll set up our body and wrap.
body { font: normal 11px "Helvetica Neue", Helvetica, sans-serif; } .wrap { width: 50px; height: 100px; position: absolute; top: 50%; left: 50%; margin: -50px 0px 0px -25px; }
In our body tag we’re using the font shorthand to set our font-style, variant and weight to normal and our size to 11px and our font-family to “Helvetica Neue”, Helvetica, sans-serif.
Our .wrap selector is essentially positioning our clock in the middle of the page. It’s using position: absolute and setting the top and left to 50% to center it from the left and top of the screen. We set the margin-top to -50px in order center the center of our 100px tall div in the middle of the screen, and -25px margin-left to find the center of our 50px width.
Next, let’s set up the unordered list and lines.
ul#initial { list-style-type: none; width: 50px; height: 100px; padding: 0px; position: relative; } ul#initial li { position: absolute; top: 0; left: 0; text-align: center; width: 50px; }
So we have our lazily named initial ul. Our first move is to remove the dots next to our list items so we’ll set list-style-type: none. Then we’ll set our width to 50px and our height to 100px. We’re doing each of our halves of an image will be 50px tall so we’re doing 100px to hold both halves. Lastly, we’ll set position: relative. This will come into play so we can set our position: absolute on our li elements and allow us to position our li relative to the position of our ul.
.first { z-index: 3; } .second { -webkit-animation: zindex 1s 1s linear both; z-index: 2; }
These rules are setting the z-index values of our two li elements. .first contains our first number, 1, and .second contains our next number, 2. We set the z-index: 3 on our first li in order to have it on top of our second which has a z-index: 2. We then call our first animation (Note: I’m just using the -webkit- vendor prefix because I’m working in Chrome. Use -moz- for Firefox and don’t use IE. Or use the jQuery plugin PrefixFree and just use animation: as your rule with no prefix.) Our animation rule names our animation zindex and then sets the timing of the animation to 1 second, the next value sets our delay to 1 second (don’t want our second number popping over our first too soon), the next value sets the speed curve of our animation to linear, and finally we set our animation fill mode to both. Let’s take a look at the keyframes for the actual animation.
@-webkit-keyframes zindex { 0% { z-index: 2; } 5% { z-index: 4; } 100% { z-index: 4; } }
Basically this takes our second li and brings it to z-index: 4 so it lays overtop of the first number when the animation is complete.
So now let’s set up our the top and bottom areas of our first number.
.flipthis { height: 50px; width: 50px; background: #ff0000; color: #fff; -webkit-transform-origin: 50% 100%; overflow: hidden; position: absolute; top: 0; left: 0; border-radius: 5px 5px 0px 0px; -webkit-animation: flipthis 1s linear; -moz-animation: flipthis 1s linear; animation: flipthis 1s linear; } .flipthis-down { height: 50px; width: 50px; background: #ff0000; color: #fff; overflow: hidden; position: absolute; top: auto; left: 0; bottom: 0; border-radius: 0px 0px 5px 5px; } .digit { height: 200%; font-size: 80px; position: absolute; width: 50px; text-align: center; text-shadow:0px 1px 2px rgba(224,224,224,0.87); } .flipthis-down .digit { bottom: 0; } .flipthis:after { content: ""; position:absolute; top:49px; left:0; z-index: 5; width: 100%; height: 3px; background-color: rgba(255,255,255,.4); }
So this isn’t the best CSS, but we’re just testing out functionality to play around here. We’ve broken down our number into a top and bottom half, flipthis (top) and flipthis-down (bottom). I was not kidding when I said I did not put much though into these names. Basically we’re setting each div to be a 50×50 red box with white text. Then we set the position: absolute and top: 0 so our top div is at the top and set our bottom div to bottom: 0. Guess why. Our border-radius rule in the top sets the top and right corner to 5px and the one in our down rule sets the bottom and left corners to 5px. We then jack our font-size up in the .digit class so that our number extends into outside the div (but is hidden by our overflow), and we set the height to 200% so it places the text in 100px instead of 50px and will allow us to position it correctly. That’s why the position of digit is absolute and the .flipthis-down .digit has a bottom: 0 so the text in the bottom is aligned correctly by moving the 200% tall div to have the same bottom as the 50px div that contains it. .flipthis:after simply sets the white line across the middle of the clock.
The real fun in this set of CSS comes with the animation and transform rules. In the animation rule we’re animating the top so half of the digit so that it rotates down linearly over 1 second. In the transform origin rule we’re setting the origin of the transform to 50% on the x-axis and 100% on the y-axis. Play around with the numbers to see how it works.
Let’s check out the actual animation.
@-webkit-keyframes flipthis { 0% { transform: rotateX(0deg); -webkit-transform: rotateX(0deg); /* Safari and Chrome */ -moz-transform: rotateX(0deg); /* Firefox */ } 100% { transform: rotateX(-90deg); -webkit-transform: rotateX(-90deg); /* Safari and Chrome */ -moz-transform: rotateX(-90deg); /* Firefox */ } }
So we start at rotateX(0deg) and rotate to (-90deg) over the 1 second defined in the animation call. So this will start our flat and rotate it on the x-axis to 90 degrees.
.flipthis2 { height: 50px; width: 50px; background: #ff0000; color: #fff; overflow: hidden; position: absolute; top: 0; left: 0; border-radius: 5px 5px 0px 0px; } .flipthis2-down { height: 50px; width: 50px; background: #ff0000; color: #fff; -webkit-transform-origin: 50% 0%; overflow: hidden; position: absolute; top: auto; left: 0; bottom: 0; border-radius: 0px 0px 5px 5px; -webkit-animation: flipthis-down 1s 1s linear; -moz-animation: flipthis-down 1s 1s linear; animation: flipthis-down 1s 1s linear; } .flipthis2-down .digit { bottom: 0; } .flipthis2:after { content: ""; position:absolute; top:49px; left:0; z-index: 5; width: 100%; height: 3px; background-color: rgba(255,255,255,.4); }
You’ll notice a lot of repeating code here. That’s a quick fix to make this work. The main difference between this and the code above (other than the selectors) is the new animation we’re calling on the down digit of our second number. We also set or transform origin different and this time we set it on the down section. That’s because we’ll be animating the bottom half down. We also have an extra 1s. That’s the delay and will essentially start this animation when previous animation ends. So let’s take a look at that code.
@-webkit-keyframes flipthis-down { 0% { transform: rotateX(90deg); -webkit-transform: rotateX(90deg); /* Safari and Chrome */ -moz-transform: rotateX(90deg); /* Firefox */ } 100% { transform: rotateX(0deg); -webkit-transform: rotateX(0deg); /* Safari and Chrome */ -moz-transform: rotateX(0deg); /* Firefox */ } }
So this animation will start with our x rotated to 90 degrees already at the beginning and rotates to a flat 0 degrees at the bottom.
So we’ve got an animation flipping over now, but we’re missing the cool perspective. Let’s add that in real quick.
a.derp { -webkit-perspective: 200px; display: block; width: 50px; height: 100px; }
And there you go. We’ve got our 1 number on top and then over 1 second the 1 flips down to the middle and at that point the 2 appears to flip down from the middle to the bottom over top of the one. Check out a demo.