Skip to content

Instantly share code, notes, and snippets.

@qcgm1978
Created December 31, 2018 04:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qcgm1978/7263a2ac9f683d7afa1a35f26973da24 to your computer and use it in GitHub Desktop.
Save qcgm1978/7263a2ac9f683d7afa1a35f26973da24 to your computer and use it in GitHub Desktop.
The Solar System in CSS
<div class="solar-system">
<div class="sun">
<div class="label">
<h2 class="label__title">Sun</h2>
</div>
<div class="system system--mercury">
<div class="planet planet--mercury"></div>
<div class="label">
<h2 class="label__title">Mercury</h2>
</div>
</div>
<div class="system system--venus">
<div class="planet planet--venus"></div>
<div class="label">
<h2 class="label__title">Venus</h2>
</div>
</div>
<div class="system system--earth">
<div class="planet planet--earth"></div>
<div class="label">
<h2 class="label__title">Earth</h2>
</div>
<div class="moon moon--moon">
<div class="moon__body body"></div>
</div>
</div>
<div class="system system--mars">
<div class="planet planet--mars"></div>
<div class="label">
<h2 class="label__title">Mars</h2>
</div>
</div>
<div class="asteroids">
<div class="asteroids__inner"></div>
</div>
<div class="system system--jupiter">
<div class="planet planet--jupiter"></div>
<div class="label">
<h2 class="label__title">Jupiter</h2>
</div>
<div class="moon moon--ganymede">
<div class="moon__body body"></div>
</div>
<div class="moon moon--calisto">
<div class="moon__body body"></div>
</div>
<div class="moon moon--io">
<div class="moon__body body"></div>
</div>
<div class="moon moon--europa">
<div class="moon__body body"></div>
</div>
</div>
<div class="system system--saturn">
<div class="planet planet--saturn">
<div class="ring ring--a"></div>
<div class="ring ring--b"></div>
<div class="ring ring--c"></div>
<div class="ring ring--f"></div>
<div class="planet__body"></div>
<div class="ring2 ring--a"></div>
<div class="ring2 ring--b"></div>
<div class="ring2 ring--c"></div>
<div class="ring2 ring--f"></div>
</div>
<div class="label">
<h2 class="label__title">Saturn</h2>
</div>
<div class="moon moon--titan">
<div class="moon__body body"></div>
</div>
<div class="moon moon--rhea">
<div class="moon__body body"></div>
</div>
<div class="moon moon--iapetus">
<div class="moon__body body"></div>
</div>
<div class="moon moon--dione">
<div class="moon__body body"></div>
</div>
<div class="moon moon--tethys">
<div class="moon__body body"></div>
</div>
</div>
<div class="system system--uranus">
<div class="planet planet--uranus">
</div>
<div class="label">
<h2 class="label__title">Uranus</h2>
</div>
<div class="moon moon--titania">
<div class="moon__body body"></div>
</div>
<div class="moon moon--oberon">
<div class="moon__body body"></div>
</div>
<div class="moon moon--umbriel">
<div class="moon__body body"></div>
</div>
<div class="moon moon--ariel">
<div class="moon__body body"></div>
</div>
</div>
<div class="system system--neptune">
<div class="planet planet--neptune">
<div class="ring ring--galle"></div>
<div class="ring ring--lassell"></div>
<div class="planet__body"></div>
<div class="ring2 ring--galle"></div>
<div class="ring2 ring--lassell"></div>
</div>
<div class="label">
<h2 class="label__title">Neptune</h2>
</div>
<div class="moon moon--triton">
<div class="moon__body body"></div>
</div>
</div>
<!-- Sorry Pluto, You're not a planet -->
<!--
<div class="system system--pluto">
<div class="planet planet--pluto"></div>
<div class="planet__info">
<div class="planet__panel">
<h2 class="planet__title">Pluto</h2>
</div>
</div>
<div class="moon moon--charon">
<div class="moon__body body"></div>
</div>
</div>
-->
</div>
</div>
// Nothing to see here :)
// VARIABLES
// Body diametres in km at equator
// Planet diametres
$mercury-diam: 4879;
$venus-diam: 12104;
$earth-diam: 12576;
$mars-diam: 6792;
$jupiter-diam: 142984;
$saturn-diam: 120536;
$uranus-diam: 51118;
$neptune-diam: 49528;
$pluto-diam: 2390;
$asteroid-inner-diam:329115316;
$asteroid-outer-diam:478713186;
// The sun is really 695,508km across, but that's too large for us so we''ll just set it to be twice the size of the Earth.
// Uncomment the line below and comment out the one after that to see the Sun to scale.
// $sun-diam: 695508;
$sun-diam: $earth-diam * 2;
// set the base size
// 1 Earth diametre = 0.3% of the viewport width
$scale: .3vw;
$base: $earth-diam;
// calculate body sizes reltive to base size (Earth)
$sun: $sun-diam / $base;
$mercury: $mercury-diam / $base;
$venus: $venus-diam / $base;
$earth: $earth-diam / $base;
$mars: $mars-diam / $base;
$jupiter: $jupiter-diam / $base;
$saturn: $saturn-diam / $base;
$uranus: $uranus-diam / $base;
$neptune: $neptune-diam / $base;
$pluto: $pluto-diam / $base;
// set the scale of the orbits
$orbit-scale: 4498300000 / (48 - ($sun / 2)); // Neptune's orbit divided by whatever taking into account the size of the sun. 100 = 100% window width
$asteroid-inner: $asteroid-inner-diam / $orbit-scale * 2.083 + ($sun/2) +vw;
$asteroid-outer: $asteroid-outer-diam / $orbit-scale * 2.083 + ($sun/2) +vw;
// ---------------------------------------------------------------------
// MIXINS
@mixin positioning {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
@mixin centring {
display: flex;
align-items: center;
justify-content: center;
}
@mixin sizing($diametre) {
width: $diametre+rem;
height: $diametre+rem;
}
@mixin planet($planet, $diametre, $orbit, $duration, $day, $axial-tilt, $reverse) { // Planet name | Diametre | Orbit Diametre | Planetary year in Earth days | Planetary day in Earth days | Axial tilt (degrees) | rotation direction: anti-clockwise = true
// variables
$dia: $diametre +rem;
$rad: $diametre / 2 +rem;
$orb: $orbit / $orbit-scale + ($sun / 2);
$dur: $duration / 10 +s;
$day: $day * 5;
width: $dia;
height: $dia;
left: calc(50% + #{$orb +vw});
margin-top: -$rad;
margin-left: -$rad;
animation: orbit $dur linear infinite;
transform-origin: -$orb +vw;
$reverse: false !default;
@if $reverse == false {
.planet {
animation:
counter+-$planet $dur linear infinite,
rotate+-$planet $day+s linear infinite;
&:after {
transform-origin: $rad;
transform: translate(-50%) rotate(-$axial-tilt+deg);
}
&__body {
animation: rotate+-$planet $day+s linear infinite;
}
}
}
@else {
.planet {
animation:
counter+-$planet $dur linear infinite,
rotateb+-$planet $day+s linear infinite;
&:after {
transform-origin: $rad;
transform: translate(-50%) rotate(-$axial-tilt+deg);
}
&__body {
animation: rotateb+-$planet $day+s linear infinite;
}
}
}
.label {
animation: desc-counter+-$planet $dur linear infinite;
}
@keyframes rotate-#{$planet} {
from { background-position: 0 0, 0 0; }
to { background-position: 0 0, -200% 0; }
}
@keyframes rotateb-#{$planet} {
from { background-position: 0 0, 0 0; }
to { background-position: 0 0, 200% 0; }
}
@keyframes counter-#{$planet} {
from { transform: rotate(0 + (-$axial-tilt/2) +deg); }
to { transform: rotate(360 + (-$axial-tilt/2) +deg); }
}
@keyframes desc-counter-#{$planet} {
from { transform: rotate(0 +deg); }
to { transform: rotate(360 +deg); }
}
}
@mixin moon($diametre, $orbit, $duration, $planet, $moon) { // Moon diamtere (km) | Orbital Diametre (km) | Orbit duration (Earth Days) | Planet orbitted
// variables
$dia: $diametre / $base +rem;
$rad: $diametre / 2;
$orb: $orbit / 20 / $base + ($planet / 2);
$dur: $duration +s;
width: $dia;
height: $dia;
left: calc(50% + #{$orb+rem});
top: 50%;
animation: orbit $dur linear infinite;
transform-origin: -$orb+rem;
}
@mixin ring($width, $radius) { // Ring width (km) | Ring radius (km)
border-width: $width / $base +rem;
height: $radius * 2 / $base +rem;
width: $radius * 2 / $base +rem;
}
// ---------------------------------------------------------------------
* {
box-sizing: border-box;
}
html, body {
height: 100%;
}
html {
font-size: $scale;
}
body {
background: #1c1c1c;
font-family: 'Titillium Web', sans-serif;
@include centring;
}
.solar-system {
@include centring;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.planet,
.moon,
.sun,
.fill {
border-radius: 50%;
}
.sun {
background: radial-gradient( circle, yellow, #FDB813 );
@include centring;
@include sizing($sun);
position: relative;
}
// PLANETS ================================================================= //
.system {
@include positioning;
// Planet name | Diametre | Orbit Diametre (km) | Planetary year (Earth days) | Planetary day (Earth days) | Axial tilt (degrees) | rotation: anti-clockwise = true
&--mercury {
@include planet(Mercury, $mercury, 57900000, 88, 59, 0.03, false);
}
&--venus {
@include planet(Venus, $venus, 108200000, 225, -243, 2.64, true);
}
&--earth {
@include planet(Earth, $earth, 149600000, 365, 1, 23.44, false);
}
&--mars {
@include planet(Mars, $mars, 227900000, 687, 1.025, 25.19, false);
}
&--jupiter {
@include planet(Jupiter, $jupiter, 778400000, 10756, 0.375, 3.13, false);
}
&--saturn {
@include planet(Saturn, $saturn, 1426700000, 10756, 0.416, 26.73, true);
}
&--uranus {
@include planet(Uranus, $uranus, 2871000000, 30687, 0.542, 82.23, false);
}
&--neptune {
@include planet(Neptune, $neptune, 4498300000, 60190, 0.666, 28.32, false);
}
&--pluto {
@include planet(Pluto, $pluto, 5906400000, 90560, 6.39, 57.47, false);
}
}
.planet__body,
.planet {
background-size: cover;
background-position: 0 0;
background-repeat: repeat-x;
}
.planet__body {
height: 100%;
border-radius: 50%;
position: relative;
z-index: 1;
background-color: rgba(247, 223, 180, 1);;
}
.planet {
width: 100%;
height: 100%;
&--mercury {
background-image:
radial-gradient( circle at top left, transparent, #000 ),
url(http://space.craigomatic.co.uk/solar-system/images/mercury.svg);
}
&--venus {
background-image:
radial-gradient( circle at top left, transparent, #000 ),
url(http://space.craigomatic.co.uk/solar-system/images/venus.svg);
}
&--earth {
background-image:
radial-gradient(circle at top left, transparent, #000),
url(http://space.craigomatic.co.uk/solar-system/images/earth.svg);
background-color: #3454DF;
}
&--mars {
background-image:
radial-gradient( circle at top left, transparent, #000 ),
url(http://space.craigomatic.co.uk/solar-system/images/mars.svg);
}
&--jupiter {
background-image:
radial-gradient(circle at top left, transparent, #000),
// duplicating the background image fixes a bug where a gap appears between animated repeating images at certain scales in Chrome
url(http://space.craigomatic.co.uk/solar-system/images/jupiter.svg),
url(http://space.craigomatic.co.uk/solar-system/images/jupiter.svg);
}
&--saturn .planet__body {
background-image:
radial-gradient( circle at top left, transparent, #000 ),
// duplicating the background image fixes a bug where a gap appears between animated repeating images at certain scales in Chrome
url(http://space.craigomatic.co.uk/solar-system/images/saturn.svg),
url(http://space.craigomatic.co.uk/solar-system/images/saturn.svg);
}
&--uranus {
background-image:
radial-gradient( circle at bottom left, transparent, #000 ),
linear-gradient( #acdee5, #7faab1)
}
&--neptune .planet__body{
background-image:
radial-gradient( circle at top left, transparent, #000 ),
// duplicating the background image fixes a bug where a gap appears between animated repeating images at certain scales in Chrome
url(http://space.craigomatic.co.uk/solar-system/images/neptune.svg),
url(http://space.craigomatic.co.uk/solar-system/images/neptune.svg);
}
&--pluto {
background-image: radial-gradient( circle at top left, #E9E8D2, #000 );
}
}
// PLANET RINGS ================================================================= //
.ring,
.ring2 {
border-style: solid;
border-color: lightyellow;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate3d(1, 0, 0, 80deg);
}
.ring {
border-top-color: transparent;
border-right-color: transparent;
z-index: 2;
}
.ring2 {
border-bottom-color: transparent;
border-left-color: transparent;
z-index: 0;
}
.ring--a {
// Inner diametre (km) | Outer diametre (km)
@include ring(14600, 136000);
opacity: .6;
}
.ring--b {
@include ring(25500, 117580);
opacity: .4;
}
.ring--c {
@include ring(17500, 92000);
opacity: .2;
}
.ring--f {
@include ring(500, 117580);
opacity: .8;
}
.ring--galle {
@include ring(2000, 42900);
opacity: .1;
}
.ring--lassell {
@include ring(4000, 57000);
opacity: .1;
}
// MOONS ================================================================= //
.moon {
position: absolute;
z-index: 0;
&__body {
background: white;
width: 100%;
height: 100%;
border-radius: 50%;
}
&--moon {
@include moon(3475, 384400, 27.322, $earth, moon);
}
&--ganymede {
@include moon(5262, 1070400, 7.155, $jupiter, ganymede);
}
&--calisto {
@include moon(4821, 1882700, 16.689, $jupiter, calisto);
}
&--io {
@include moon(3643, 421800, 1.769, $jupiter, io);
}
&--titan {
@include moon(5150, 1221900, 15.945, $saturn, titan);
}
&--rhea {
@include moon(1529, 527070, 4.518, $saturn, rhea);
}
&--iapetus {
@include moon(1471, 3560900, 79.330, $saturn, iapetus);
}
&--dione {
@include moon(1123, 377420, 2.737, $saturn, dione);
}
&--tethys {
@include moon(1066, 294700, 1.888, $saturn, tethys);
}
&--titania {
@include moon(1578, 436300, 8.706, $uranus, titania);
}
&--oberon {
@include moon(1523, 583500, 13.463, $uranus, oberon);
}
&--umbriel {
@include moon(1169, 266000, 4.144, $uranus, umbriel);
}
&--ariel {
@include moon(1158, 190900, 2.520, $uranus, ariel);
}
&--triton {
@include moon(2707, 354760, 5.877, $neptune, triton);
}
&--charon {
@include moon(1210, 19570, 6.387, $pluto, charon);
}
}
// ASTEROID BELT ================================================================= //
.asteroids {
position: absolute;
width: $asteroid-outer;
height: $asteroid-outer;
border-radius: 50%;
background-image: url(http://space.craigomatic.co.uk/solar-system/images/asteroids.png);
background-size: cover;
opacity: .3;
z-index: -1;
animation: orbit 120s linear infinite;
&__inner {
@include positioning;
width: $asteroid-inner;
height: $asteroid-inner;
border-radius: 50%;
background: #1c1c1c;
}
}
// LABELS ================================================================= //
.label {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
color: white;
opacity: 0;
transition:
all .6s ease 0s,
width 0s ease .6s;
&__title {
position: absolute;
top: calc(100% + 10px);
left: 50%;
font-size: 14px;
font-weight: 300;
margin: 0;
border-top: 1px solid #999;
border-radius: 4px;
background: rgba(28,28,28,0.6);
transform: translateX(-50%);
padding: 5px 20px;
transform-origin: top center;
width: auto;
&:before {
content: '';
position: absolute;
left: 50%;
top: -10px;
border: 5px transparent solid;
border-bottom-color: #999;
transform-origin: top left;
transform: translateX(-50%);
}
}
.sun:hover & {
transition:
all .6s ease,
width 0s;
opacity: 1;
.label {
opacity: 0;
}
}
}
@keyframes orbit {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}

The Solar System in CSS

An animated simulation of the Solar System using only Sass/CSS. No Javascript involved.

All planets are to scale in comparison to the earth which is set to 0.3% of the browser window width. The sun is not to scale, its too big.

The scale of the orbits is set to the width of the browser window, with the diametre of Neptune's orbit set at 96% and all others in proportion to that rather than to the size of the planets as this would have made the planets way too small to see. Orbits are assumed to be round and on the same plane, which of course they are not.

All orbit and rotational speeds are to scaled to one Earth year and one Earth day. One Earth year (once round the sun) is set at one second and one Earth day (one planetary rotation) is 0.2 seconds.

Not all planetary objects are shown. I've left out dwarf planets and a lot of moons that are too small to see at this scale.

Distances, sizes and timings are taken from various sources

Best viewed on larger screens.

A Pen by youth on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment