An Orrery in pure CSS3 (ok, Sass generated). Still WIP. Having great fun with it!
A Pen by Tady Walsh on CodePen.
An Orrery in pure CSS3 (ok, Sass generated). Still WIP. Having great fun with it!
A Pen by Tady Walsh on CodePen.
| <div class="system"> | |
| <div class="sun"></div> | |
| <div class="mer-path"></div> | |
| <div class="mer"></div> | |
| <div class="ven-path"></div> | |
| <div class="ven"></div> | |
| <div class="ear-path"></div> | |
| <div class="ear"><div class="lune"></div></div> | |
| <div class="mar-path"></div> | |
| <div class="mar"> | |
| <div class="pho"></div> | |
| <div class="dem"></div> | |
| </div> | |
| <div class="jup-path"></div> | |
| <div class="jup"> | |
| <div class="spot"></div> | |
| <div class="jove io"></div> | |
| <div class="jove eur"></div> | |
| <div class="jove gan"></div> | |
| <div class="jove cal"></div> | |
| </div> | |
| <div class="sat-path"></div> | |
| <div class="sat"> | |
| <div class="f-ring"></div> | |
| <div class="a-ring"></div> | |
| <div class="b-ring"></div> | |
| <div class="c-ring"></div> | |
| </div> | |
| <div class="ura-path"></div> | |
| <div class="ura"> | |
| <div class="e-ring"></div> | |
| </div> | |
| <div class="nep-path"></div> | |
| <div class="nep"> | |
| <div class="spot"></div> | |
| </div> | |
| <div class="plu-path"></div> | |
| <div class="plu"></div> | |
| </div> |
| /** | |
| * I was out the other evening looking at Venus with the setting sun and thought, I wonder where all the planets | |
| * are in relation to each other right now. I knew what an Orrery was, but I'd never built one. So, given my mate | |
| * Donovan's (@donovanh: http://cssanimation.rocks/) penchant for CSS animation, I thought I'd give it a go | |
| * building one in pure CSS. | |
| * | |
| * Many thanks to @aidandore and @iandevlin too for suggestions and improvements | |
| * | |
| * Chin up Pluto. You'll always be a planet to me... | |
| * | |
| * Tady: http://tady.me | |
| * @tadywankenobi | |
| */ | |
| /** | |
| * Move in a circle without wrapper elements | |
| * Idea by Aryeh Gregor, simplified by Lea Verou, borrowed by me! | |
| */ | |
| @mixin vp-anim($radius,$pname, $deg: 360deg) { | |
| @-webkit-keyframes rot-#{$pname} { | |
| from { | |
| -webkit-transform: rotate(0deg) | |
| translatey(-$radius) | |
| rotate(0deg); | |
| } | |
| to { | |
| -webkit-transform: rotate(360deg) | |
| translatey(-$radius) | |
| rotate(-$deg); | |
| } | |
| } | |
| @-moz-keyframes rot-#{$pname} { | |
| from { | |
| -moz-transform: rotate(0deg) | |
| translatey(-$radius) | |
| rotate(0deg); | |
| } | |
| to { | |
| -moz-transform: rotate(360deg) | |
| translatey(-$radius) | |
| rotate(-$deg); | |
| } | |
| } | |
| @-keyframes rot-#{$pname} { | |
| from { | |
| transform: rotate(0deg) | |
| translatey(-$radius) | |
| rotate(0deg); | |
| } | |
| to { | |
| transform: rotate(360deg) | |
| translatey(-$radius) | |
| rotate(-$deg); | |
| } | |
| } | |
| } | |
| $baseUnit: 0.1; // Speed of Orrery. At 1, 1 sec = 1 day | |
| $sunRad: 72px; // Radius of the sun, added to orbit radii | |
| $rFactor: 2; // Adding a radius factor so orbit radii are easier to observe | |
| $middleOffset: 800px; | |
| $scale: 0.75; // Play around with changing this to change the visible motion default: 0.75 | |
| $middle: $middleOffset*(1/$scale); | |
| $planets: ( | |
| ('mer',8.8s*$baseUnit,(6px*$rFactor)+$sunRad,1.75px,#888), | |
| ('ven',22.5s*$baseUnit,(9px*$rFactor)+$sunRad,2.75px,#f5f9be), | |
| ('ear',36.5s*$baseUnit,(15px*$rFactor)+$sunRad,3.5px,#4b94f9), | |
| ('mar',68.7s*$baseUnit,(23px*$rFactor)+$sunRad,3px,#dd411a), | |
| ('jup',433.2s*$baseUnit,(78px*$rFactor)+$sunRad,35px,#eaad3b), | |
| ('sat',1075.9s*$baseUnit,(145px*$rFactor)+$sunRad,29px,#d6cd93), | |
| ('ura',3068.7s*$baseUnit,(288px*$rFactor)+$sunRad,13px,#bfeef2), | |
| ('nep',6019s*$baseUnit,(450px*$rFactor)+$sunRad,12px,#363ed7), | |
| ('plu',9046.5s*$baseUnit,(587px*$rFactor)+$sunRad,1.5px,#963) | |
| ); | |
| body { | |
| background-color: #012; | |
| background-image: url('https://cssanimation.rocks/starwars/images/bg.jpg'); | |
| background-size: 33%; | |
| background-repeat: repeat; | |
| min-height: 2700px * $scale; | |
| } | |
| .system { | |
| position:relative; | |
| top: 0; left: 0; | |
| width:100%; | |
| height:100%; | |
| -webkit-transform: scale($scale); | |
| -moz-transform: scale($scale); | |
| transform: scale($scale); | |
| } | |
| .sun { | |
| width: $sunRad*2; | |
| height:$sunRad*2; | |
| border-radius: $sunRad; | |
| position:absolute; | |
| top: $middle; | |
| left:50%; | |
| margin: -$sunRad; | |
| //background-color: yellow; | |
| background-image: url('http://sdo.gsfc.nasa.gov/assets/img/latest/latest_256_HMIIF.jpg'); | |
| background-size:$sunRad*2; | |
| background-repeat:no-repeat; | |
| } | |
| @each $planet in $planets { | |
| $name: nth($planet, 1); | |
| $orb: nth($planet,2); | |
| $rad: nth($planet,3); | |
| $prad: nth($planet,4); | |
| $col: nth($planet,5); | |
| @include vp-anim($rad,$name); | |
| .#{$name} { | |
| width: $prad * 2; | |
| height: $prad*2; | |
| border-radius:50%; | |
| background-color:$col; | |
| position: absolute; | |
| top: $middle; | |
| left: 50%; | |
| margin: -$prad; | |
| -webkit-animation: rot-#{$name} $orb infinite linear; | |
| -moz-animation: rot-#{$name} $orb infinite linear; | |
| animation: rot-#{$name} $orb infinite linear; | |
| z-index:200; | |
| } | |
| .#{$name}-path { | |
| $orbitPath: $rad*2; | |
| width: $orbitPath; | |
| height: $orbitPath; | |
| border-radius:50%; | |
| z-index:100; | |
| position:absolute; | |
| top: $middle; | |
| left:50%; | |
| margin:-($orbitPath / 2); | |
| border: solid 1px #444; | |
| } | |
| } | |
| @include vp-anim(7px,lune); | |
| .lune { | |
| width:2px; | |
| height:2px; | |
| background-color: #fff; | |
| position:absolute; | |
| $lunOrb: 2.7s * $baseUnit; | |
| top: 50%; | |
| left:50%; | |
| margin:-1.5px; | |
| -webkit-animation: rot-lune $lunOrb infinite linear; | |
| -moz-animation: rot-lune $lunOrb infinite linear; | |
| animation: rot-lune $lunOrb infinite linear; | |
| } | |
| .mar { | |
| background-image: repeating-linear-gradient( | |
| to bottom, | |
| #fff, | |
| #fff 1px, | |
| transparent 1px, | |
| transparent 5px | |
| ); | |
| } | |
| @include vp-anim(7px,pho); | |
| @include vp-anim(9px,dem); | |
| .pho, .dem { | |
| width:1px; | |
| height:1px; | |
| background-color: #fff; | |
| position:absolute; | |
| top: 50%; | |
| left:50%; | |
| } | |
| .pho { | |
| $phoOrb: 1.5s * $baseUnit; // Should be 0.33s but spins like it's having a fit. | |
| margin:-1px; | |
| -webkit-animation: rot-pho $phoOrb infinite linear; | |
| -moz-animation: rot-pho $phoOrb infinite linear; | |
| animation: rot-pho $phoOrb infinite linear; | |
| } | |
| .dem { | |
| $demOrb: 2s * $baseUnit; // Should be 1.25s, spins too fast | |
| margin:-1px; | |
| -webkit-animation: rot-dem $demOrb infinite linear; | |
| -moz-animation: rot-dem $demOrb infinite linear; | |
| animation: rot-dem $demOrb infinite linear; | |
| } | |
| $jupR: 35px; | |
| .jove { | |
| width:2px; | |
| height:2px; | |
| background-color: #fff; | |
| position:absolute; | |
| top: $jupR; | |
| left:50%; | |
| } | |
| @include vp-anim($jupR + 4px,io); | |
| @include vp-anim($jupR + 6px,eur); | |
| @include vp-anim($jupR + 10px,gan); | |
| @include vp-anim($jupR + 18px,cal); | |
| .io { | |
| $jioOrb: 2s*$baseUnit; | |
| -webkit-animation: rot-io $jioOrb infinite linear; | |
| -moz-animation: rot-io $jioOrb infinite linear; | |
| animation: rot-io $jioOrb infinite linear; | |
| } | |
| .eur { | |
| $jeurOrb: 3.5s*$baseUnit; | |
| -webkit-animation: rot-eur $jeurOrb infinite linear; | |
| -moz-animation: rot-eur $jeurOrb infinite linear; | |
| animation: rot-eur $jeurOrb infinite linear; | |
| } | |
| .gan { | |
| $jganOrb: 7s*$baseUnit; | |
| -webkit-animation: rot-gan $jganOrb infinite linear; | |
| -moz-animation: rot-gan $jganOrb infinite linear; | |
| animation: rot-gan $jganOrb infinite linear; | |
| } | |
| .cal { | |
| $jcalOrb: 16.5s*$baseUnit; | |
| -webkit-animation: rot-cal $jcalOrb infinite linear; | |
| -moz-animation: rot-cal $jcalOrb infinite linear; | |
| animation: rot-cal $jcalOrb infinite linear; | |
| } | |
| .jup { | |
| background-image: repeating-linear-gradient( | |
| 6deg, | |
| #797663 22px, | |
| #e1dcde 16px, | |
| #c3a992 30px, | |
| #e9ece2 30px | |
| ); | |
| } | |
| .spot { | |
| position:absolute; | |
| width:16px;height:12px; | |
| border-radius: 8px / 6px; | |
| top: $jupR+10; | |
| left:50%; | |
| background-color:#bc833b; | |
| box-shadow: 0px 0px 5px #e1dcde; | |
| border:solid 1px #e1dcde; | |
| box-sizing:border-box; | |
| -moz-box-sizing:border-box; | |
| -webkit-box-sizing:border-box; | |
| z-index:300; | |
| .nep & { | |
| background-color:darken(#343ec5, 10%); | |
| border: 0; | |
| box-shadow: none; | |
| top: 50%; | |
| left:45%; | |
| width: 10px; | |
| height: 6px; | |
| margin: -2px; | |
| border-radius: 5px / 3px; | |
| border-left:solid 1px #7ed6fe; | |
| } | |
| } | |
| $satD: 29px * 2; | |
| div[class$="-ring"] { | |
| border-radius: 50%; | |
| position:absolute; | |
| top: 50%; | |
| left:50%; | |
| opacity: 0.7; | |
| $tilt: 45deg; | |
| -webkit-transform: rotatex($tilt); | |
| -moz-transform: rotatex($tilt); | |
| transform: rotatex($tilt); | |
| } | |
| .a-ring { | |
| $ringD: $satD + 61; | |
| $ringW: 5px; | |
| border:solid $ringW #96866f; | |
| width: $ringD; | |
| height: $ringD; | |
| margin: -($ringD / 2) - $ringW; | |
| } | |
| .b-ring { | |
| $ringD: $satD + 46; | |
| $ringW: 10px; | |
| border:solid $ringW #554c3c; | |
| width: $ringD; | |
| height: $ringD; | |
| margin: -($ringD / 2) - $ringW; | |
| } | |
| .c-ring { | |
| $ringD: $satD + 37; | |
| $ringW: 9px; | |
| border:solid $ringW #574f4a; | |
| width: $ringD; | |
| height: $ringD; | |
| margin: -($ringD / 2) - $ringW; | |
| } | |
| .f-ring { | |
| $ringD: $satD + 75; | |
| $ringW: 2px; | |
| border:solid $ringW #908e8d; | |
| width: $ringD; | |
| height: $ringD; | |
| margin: -($ringD / 2) - $ringW; | |
| } | |
| $uraD: 13px * 2; | |
| .e-ring { | |
| $ringD: $uraD + 50; | |
| $ringW: 7px; | |
| border:solid $ringW #908e8d; | |
| width: $ringD; | |
| height: $ringD; | |
| margin: -($ringD / 2) - $ringW; | |
| $tilt: 0deg; | |
| $axis: 89deg; | |
| -webkit-transform: rotatex($tilt) rotatey($axis) !important; | |
| -moz-transform: rotatex($tilt) rotatey($axis) !important; | |
| transform: rotatex($tilt) rotatey($axis) !important; | |
| } | |
| .plu, .plu-path { | |
| top: $middle + 287.4px; | |
| } |