I had been working at theory11, a magic & playing cards company. One of the things we designed was a new steampunk-style deck of cards, with steam-powered machinery and lots of moving parts. Even though it was just a flat illustration on paper, it felt like it had depth and motion. I realized it could truly come to life if it was animated on the web, with realistic moving gears and pistons. If it worked on mobile web too, I could have it in my pocket at all times and easily share it with people.

Early mockup with some gears inside the logo

I started working on some concepts in Photoshop. This shape was my logo at the time, so I decided to make it into a glass window showing some animated details behind it. The layered gears seemed promising, but didn’t make enough sense on their own. Why were they spinning? What did the whole thing mean?

I started researching other things that had gears, and remembered some fancy watches I had seen with exposed gears. I decided to turn the page into a fun mechanical clock, which told different types of time and would make sense as a countdown page. If the elements had meaning instead of just being decorative, the page would have a believable story.

Most of the watches had lots of complex and mysterious components. I looked through hundreds of them to try to figure out which elements I liked most and what the common patterns were. They had small gears with many teeth, as opposed to my previous concept with huge, coarse ones. There was also an underlying structure, with screws and a thin frame to keep everything in place.

If elements weren’t just decorative, the page would have a believable story.

I wanted it to have a unique and iconic structure, but still be made of believable and classic components. The seconds hand was in the middle, doing one rotation every minute. The day of month went from 1 to 31 in the middle, but the hour was a separate dial at the top.

Since I wasn’t limited by physics or what was in real life, I added some new elements that looked interesting but never actually existed — like a magical pendulum inspired by old grandfather clocks, which was presumably the power source.

When creating the illusion of complexity, it is important not to get overwhelmed yourself. I started with 5 separate layers which would be stacked, each with gaps and perforations to reveal details below.

The bottom layers would be slightly blurred and out of focus. I knew that if I could accurately build the small details like blur, lighting, and shadows, then people’s brains would be tricked into seeing real objects rather than a bunch of DOM elements on screen.

Lunar Cycles

One subtle feature I wanted to add was a lunar cycle indicator. Some watches and clocks featured it, so I figured it should be possible to create a mechanical representation of that logic. It just needed to transition from the full moon to half, crescent, new and then back again.

It was accurate when I launched, but I think it has broken down since then. One day I will ask a swiss watchmaker how they do it, it was tricky enough with all the power of Javascript — I can’t imagine doing it with just some spinning gears.

The Prototype

Almost no one was using CSS animation at the time and the limits were very untested, so I started benchmarking things and figuring out the best way to get high performance. I used the FPS counter in Google Chrome’s about:flags to test various ideas and see what slowed things down. The Profile tab in Chrome’s Inspector was also helpful for diagnosing bottlenecks.

I quickly discovered a lot of patterns and tricks to maintain smooth performance. Maintaining 60fps wasn’t as important as never skipping or jumping — it was ok if it dropped to 50 or even 40 when a lot of things were happening. As I tested different moving elements — with varying amounts, sizes, speeds, etc — the limiting factor was more related to the size of the area being updated and not the complexity or number of polygons. This was great news for the design, because it meant I could make lots of tiny gears and extra shadows without worrying about the whole thing grinding to a halt.

It felt quite magical to not be using any Javascript to make it run.

The calculations for the gear ratios turned out to be quite straightforward since each element had an animation-duration property for one revolution. Each one was proportional to the number of teeth it had, and then I added a global multiplier to change the speed while all of the gears still interacted with each other perfectly.

Orange lines for easier visualization of gear ratios.

I put together a really quick proof of concept to see if it would actually work. It had directional highlights and shadows, which were a really subtle effect but really helped sell the illusion. It felt quite magical to not be using any Javascript to make it run, either. I kept the page open for an hour and it ran smoothly the whole time. When it even ran perfectly on my iPhone, I knew this was the start of something amazing.

Now I just had to figure out how to expand the same technique to my mockup, with hundreds of tiny components instead of 4 big gears.

The solution was quite simple — keep the animating area small.

I had tried to do immersive, fullscreen animations before and it typically ended in tears. We had spent a whole year designing a new company site with beautiful full-page transitions, only to realize that it slowed down too much once content was added.

Hardware-accelerated CSS transformations hinted at much better performance, but the math of stretching elements across big screens still didn’t look good. Exponential growth guaranteed that trying to grow to large windows on big monitors at some point just won’t be able to keep up, as the number of pixels being animated quickly increase beyond the rendering capacity of even the most powerful machines. Things like retina displays would further increase the load.

The size of the animation is more limiting than the complexity.

The clock was a fixed size (256x256) that wouldn’t stretch out of control even on a huge window or at the higher density of a retina display. It was tempting to make it bigger on a large screen to fill up the space, but restricting it to the small square meant the animations would be consistently smooth.

It was the big tradeoff that made everything possible. This is now one of my core principles for creating smooth animations: the size of the animation is more limiting than the complexity of the motion. In general, you can get away with a lot of crazy stuff if you just keep it in a small area.

The rest of the page would be filled with a really detailed but completely static texture. It would need a big image, but would perform well after the initial download. Even though there were lots of different gears and other pieces, I combined everything into just a few sprites so it would load as quickly as possible.