demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

You have been on this page for
  • 9
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 0
  • 1
  • 8
  • 9
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 0
  • 9
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 0

seconds.

CSS3 Timer With Keyframe Animation

css / animation

Estimated reading time: 3 minutes, 11 seconds

This article started in typical fashion for me: that is, as another topic entirely. I plan to write an article on animated CSS3 media query transitions, but I was sidetracked by the question of how to display a changing browser width using alone. Thus, this CSS3 odometer; for the purpose of this article, I’ve turned it into a timer.

Ultimately the technique shown here could be put to a lot of uses. First, an explanation of the basic markup:

The display needs three “wheels” of numbers for each segment of the timer, so a series of lists makes eminent sense. As you will see, all of the lists will move to the beat of the same routine. They’re also all wrapped in a <div> with an id of timer.

You have been on this page for
<div id=timer>
<ul id=timer-tens>
<li>8<li>9<li>0<li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9
</ul>
<ul id=timer-ones>
<li>9<li>0<li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9<li>0
</ul>
</div>
seconds.</div>

Note that the numerals above and below the digit shown in the center of the wheel at any moment are included.

(I would have dearly loved to use a proper ordered list to display the numbers, but the fact that most browsers do not yet support the start attribute for ordered lists, and my desire to show a glimpse of the broader counter, made that impractical. I’ve not shown the code for the hundreds-of-seconds counter to save space).

Then the CSS. Obviously, I need to restrict the visible area of each list. That will be the job of the containing div:

div#timer { display: inline-block; height: 3.6rem; overflow: hidden; }

I’ve used inline-block so the div will still fall in line with the surrounding text, but still be provided with a height. Let’s look at the CSS for the counters:

div#timer ul { display: inline-block; list-style-type: none; width: 2rem;  padding-left: 0; margin-top: 0; position: relative; top: -1.3rem; line-height: 32px; }

This is pretty simple. The line-height specified here will interact with the general rules for the body:

body { background: #000; color: #fff; text-align: center; font-size: 32px; }

The two values guarantee that every digit in both lists is separated by the same amount of vertical space. It’s this until that we use to move the counters in the animation:

@keyframes rollover {
       0% { top: -51px; }
      10% { top: -83px; }
      20% { top: -115px; }
      30% { top: -147px; }
      40% { top: -179px; }
       50% { top: -211px; } 
      60% { top: -243px; }
      70% { top: -275px; }
      80% { top: -307px; }
      90% { top: -339px; }
    100% { top: -371px; }
}

The spacing of the numerals means that each animation sequence will start and end on the same digit, and that every numeral will always be displayed in the center of its wheel.

Now the really neat part: the animation of the tumblers. I wanted the movement between each numeral to be a very deliberate “tick”, so I created a custom easing curve and applied it to every step of the animation:

ul#timer-ones { animation: rollover 10s cubic-bezier(1.000, 0.005, 0.995, 0.090) infinite; }

The cool part is the fact that we apply the exact same animation sequence to the tens-of-seconds counter, as it moves in exactly the same way, just over a greater amount of time:

ul#timer-tens { animation: rollover 100s cubic-bezier(1.000, 0.005, 0.995, 0.090) infinite; }

That’s essentially it, with the addition of a gradient for the div and alpha-masked, absolutely positioned PNG images inside to “shadow” the tumblers.

(For this article I haven’t turned on the animation for the hundreds-of-seconds counter, as I don’t expect anyone to stick around on the page for that long… that said, it will be very interesting to look at my Google Analytics numbers later this week to see if the time-on-page metric has gone up due to visitors being obsessed, Hook-like, with a ticking clock).

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.