The orrery at the top of this site is an experiment in CSS 3 animation. (You might need a more modern browser to see it in action.) It uses data from nasa.gov to accurately represent how planets rotate around our sun.
For performance reasons, I’m only showing the first 6 moons (Luna, Phaebos & Daemos of Mars, and Io, Ganymede, & Europa of Jupiter). They are revolving accurately, but have been all been significantly slowed by an arbitrary amount in order to render them visible in the animation.
Orreries are mechanical models of the solar system, intended to model how fast planets revolve around the sun. Typically they are not to scale in terms of size or distance from the sun, but rather are an attempt to achieve a highly accurate model of planetary orbit relative to each other with clockwork gearing.
The orrery at the top of this page is visually stylized in terms of planetary placement, orbital size, and shape — however, the planets really do rotate at those speeds relative to each other.
Orreries have been a long-held fascination of mine. I find the natural revolutions of the planets to be exquisitely beautiful. This clip is from a test render I did many years ago which shows gearing that results in a extremely accurate rotations and revolutions of the Earth, in a (virtual) mechanical model.
For my CSS orrery at the top of the page, I chose to include both Pluto and Eris to show how slowly they revolve relative to celestial bodies closer to the sun. (Tip: if you can’t see some planets, try shrinking your browser width.)
The code for the orrery is posted on github if you want to take a detailed look. Here’s a brief walkthrough of the relevant bits.
The markup to generate the orbital rings and planets themselves is relatively simple. Here’s all it takes for Earth — CSS takes care of the color, shape, positioning, and rotation animation:
SCSS function calls
The adjustments to the planets were made by tweaking the following mixin calls until the planets were sized and laid out how I wanted. I mostly eyeballed the orbit size, position, and size of the planets by beginning with accurate numbers and making small adjustments.
Mixin to build the planets
The mixin itself is fairly crude, but it essentially turns a
into a round object using border-radius. A similarly round
positions the planet right on the edge of the orbit.
The reason I used nesting pseudo objects is because it simplifies the animation process by just requiring the
.orbit element to rotate. Everything else is a child of that, so rotates freely while also following the rotation of its parent.
The CSS animation process
As an example, here’s how we get the Earth to rotate. This block of CSS is the main
engine that will rotate an object indefinitely. We’ll later use the name of this keyframe animation (‘year’) for the
This sets up how fast the planets should rotate relative to each other, modified by the
$speed variable. The speed value was used to fine-tune the speed that the planets rotated altogether so I could adjust it easily. I included Earth as an example below.
Why not use SVG animation?
The main reason for not using SVG animation is that I was trying to learn more about CSS animation performance for rotate transforms. If I do a v2 of the orrery at any point in the future, I will probably try to just create vector graphics of the planets and use an svg animation library like Snap.svg.
In general, the animation is very CPU intensive for rotating this many objects. I included the pause button to limit the resources the page takes up, but it’s something I’d like to fix in the future.