Let's build the planets in our solar system — complete with their relative rotation speed, tilt, and other photorealistic goodies — using only CSS!

As part of this week's Planet Challenge (#cpc-planets #codepenchallenge), I'll be dissecting part of my Solar CSSystem demo I posted in April 2019:

As the great science communicator Carl Sagan once said:

"If you wish to make an apple pie from scratch, you must first invent the universe."

Welp... there's a lot going on in that apple pie, so let's unpack the recipe one step at a time.

All of the data used in this demo was obtained from NASA's Planetary Fact Sheet.

# Rotation

To keep things simple, let's focus on just one planet for now. I'll be use Mars 🔴 in this demo (since my name is Rob Di Marz o after all 🙃), but feel free to use any planet you're vibing with.

• Find an image of the entire planet's surface. Make sure the left and right sides of the map can connect seamlessly.
• Set CSS variables for the image and day length (in hours) of the planet. (Note: These values can also be applied directly in CSS or stored as Sass variables, but I am using CSS variables because they're useful when looping through multiple planets later.)

``````:root {
--mars-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/332937/mars.jpg);
--mars-day: 24.6;
}
``````
• Apply the CSS variables to the planet__surface div. The biggest thing to point out here is the animation duration: calc(var(--mars-day)*.1s). This code calculates 10% of the planet's day length and measures the value in seconds instead of hours. In this example, 24.6 becomes 2.46s, which becomes the duration of one full rotation.

``````.planet__surface {
background-size: cover;
background-image: var(--mars-image);
animation: planetRotate calc(var(--mars-day)*.1s) linear infinite;
}
``````
• Animate the planet rotation by moving the background-position's x-value from 0 to -200%. This will move the image so that the next rotation flawlessly begins where the last one's ends.

``````@keyframes planetRotate {
0% {    background-position: 0% center; }
100% {  background-position: -200% center; }
}
``````

So far so good! Now let's add some...

# Tilt

• Add a border-radius to make the planet circular, because it's clearly very unplanet-like so far.
• Set another CSS variable for the planet's tilt (known in our data source as Obliquity to Orbit).

``````  --mars-tilt: rotate(25.2deg);
``````
• Apply the tilt variable to rotate the planet__surface div by the tilt amount (25.2 degrees). I'll also add an additional scale transformation to enlarge the image and overcome size distortion issues related to flat map projection.

``````  transform: var(--mars-tilt)scale(1.15);
``````
• Add an axis line to exaggerate and bring more focus to the tilt measurement.

``````  .card__planet {
&::before {
content: '';
position: absolute;
height: 200px;
z-index: -2;
left: 50%;
top: 0%;
border-left: 1px dashed rgba(255,255,255,.5);
transform: var(--mars-tilt)scale(1.2);
}
}
``````

Pretty cool! But it still feels... blah. So let's add some...

# Texture

• Set another CSS variable for the planet's primary color. To obtain this value, I used the eyedropper tool in Sketch (or whichever image editting app you choose) to select a color that is most represented in the planet.

``````    --mars-color: #c07158;
``````
• Add box-shadows and radial-gradients to the planet__atmosphere div to create the illusion of a sphere and texture of a planet. I am layering multiple properties here to create depth:

• The Inner Crest (inner left): inset 10px 0px 12px -2px rgba(255,255,255,.2)
• The Dark Side (inner right): inset -70px 0px 50px 0px black
• The Atmosphere (outer left): -5px 0px 10px -4px var(--mars-color)
• Spherical Spotlight (inner middle): radial-gradient(circle at 30% 50%, rgba(255,255,255,.2) 0%, rgba(255,255,255,0);

`````` box-shadow: inset 10px 0px 12px -2px rgba(255,255,255,.2),
inset -70px 0px 50px 0px black,
-5px 0px 10px -4px var(--mars-color);
rgba(255,255,255,.2) 0%,
rgba(255,255,255,0) 65%);
``````
• Color the axis-line with the planet's primary color, because we can.

# The Beyond...

The teachings in this blog post can be applied to any of our celestial neighbors. Give it a try with your favorite planet 🤓!

For the sake of brevity in this post, I won't go into the deeper aspects of my Solar CSSystem demo, like:

• Extending this pattern to all the planets in our solar system
• Using a Sass mixin to optimize the planet styling process
• Using Pug to iterate a dynamic HTML structure and data for each planet

Is that something you'd be interested in learning in another blog post? Let me know in the comments below!