The Solar System in CSS
Mads Stoumann

Mads Stoumann @madsstoumann

About: I'm a tech director, web developer, graphic designer, musician, blogger, comicbook-geek, LEGO-collector, food lover … as well as husband and father!

Location:
Copenhagen, Denmark
Joined:
Nov 16, 2020

The Solar System in CSS

Publish Date: Aug 25 '24
273 50

The Solar System has been done in CSS a lot of times — just search Codepen! So why do it again?

Because things get better and simpler — and we can now do a responsive solar system with just a few lines of CSS.

Let's start with some very basic markup:

<ol>
  <li class="sun"></li>
  <li class="mercury"></li>
  <li class="venus"></li>
  <li class="earth"></li>
  <li class="mars"></li>
  <li class="jupiter"></li>
  <li class="saturn"></li>
  <li class="uranus"></li>
  <li class="neptune"></li>
</ol>
Enter fullscreen mode Exit fullscreen mode

We use an ordered list, because the planets are in order.

Next, we unset the default <ol>-styles, and style it as a grid:

ol {
  all: unset;
  aspect-ratio: 1 / 1;
  container-type: inline-size;
  display: grid;
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Now, for the planet trajectories, we're going to use a "grid stack". Instead of position: absolute, and a bunch of translations, we can simply stack all the grid items with:

li {
  grid-area: 1 / -1;
  place-self: center;
}
Enter fullscreen mode Exit fullscreen mode

By setting a --d-variable (for diameter) per planet, using width: var(--d);, we get:

Trajectories

Cool! Let's add the planets using an ::after pseudo-element:

li::after {
  aspect-ratio: 1 / 1;
  background: var(--b);
  border-radius: 50%;
  content: '';
  display: block;
  width: var(--w, 2cqi);
}
Enter fullscreen mode Exit fullscreen mode

Let's ask ChatGPT to generate some nice radial-gradents for each planet — and while we're at it, let's tell it we're creating the Solar System and ask for planetary sizes between 1 and 6cqi — not completely accurate, but still maintaining a sizeable, recognizable difference:

.mercury {
  --b: radial-gradient(circle, #c2c2c2 0%, #8a8a8a 100%);
  --w: 2.0526cqi;
}

.venus {
  --b: radial-gradient(circle, #f4d03f 0%, #c39c43 100%);
  --w: 2.6053cqi;
}

.earth {
  --b: radial-gradient(circle, #3a82f7 0%, #2f9e44 80%, #1a5e20 100%);
  --w: 3.1579cqi;
}

.mars {
  --b: radial-gradient(circle, #e57373 0%, #af4448 100%);
  --w: 3.7105cqi;
}

.jupiter {
  --b: radial-gradient(circle, #d4a373 0%, #b36d32 50%, #f4e7d3 100%);
  --w: 4.8158cqi;
}

.saturn {
  --b: radial-gradient(circle, #e6dba0 0%, #c2a13e 100%);
  --w: 5.3684cqi;
}

.uranus {
  --b: radial-gradient(circle, #7de3f4 0%, #3ba0b5 100%);
  --w: 4.2632cqi;
}

.neptune {
  --b: radial-gradient(circle, #4c6ef5 0%, #1b3b8c 100%);
  --w: 6cqi;
}
Enter fullscreen mode Exit fullscreen mode

And now we have:

Solar System

To animate the planets with different trajectory speeds, we add:

li::after {
  /* previous styles */
  animation: rotate var(--t, 3s) linear infinite;
  offset-path: content-box;
}
Enter fullscreen mode Exit fullscreen mode

Notice the offset-path. That's the key to simplifying the trajectory-animations, because all we have to do to move the planet along the shape of the <li> is this:

@keyframes rotate {
  to {
    offset-distance: 100%;
  }
}
Enter fullscreen mode Exit fullscreen mode

And that's all! I asked ChatGPT to calculate the timings based on "Neptune", with a rotation-speed of 20s — and we get:


Conclusion

With just a few rules, we created a simple 2d version of the Solar System in pure CSS. If you want to dive deeper, you can:

  • use real distances and sizes (with calc())
  • add a transform: rotateX(angle) to the <ul> to make it pseudo-3D:

Basic 3D

... and maybe use matrix3d to "re-flatten" the planets?

Happy coding!


UPDATE, 27.08.24: Some readers have poined out, that the scales and distances are not correct. That is true, and is on purpose. The goal of this article is to show the powers of offset-path and grid-stacks.

However, if we were to calc the system dimensions with the Sun's width at 10cqi and the outer trajectory of Neptune at 100cqi, then we have an AU (Astronomical Unit) of 2.994cqi, and we get:

Scaled

Comments 50 total

  • Cody Antonio Gagnon
    Cody Antonio GagnonAug 25, 2024

    Awesome animation and nice use of ChatGPT for the orbits!

  • GreenerSoft
    GreenerSoftAug 25, 2024

    Bravo, that's really cool.

  • Tajebe Liyew
    Tajebe LiyewAug 25, 2024

    Wow

  • mayowa-kalejaiye
    mayowa-kalejaiyeAug 26, 2024

    Brilliant

  • Me
    MeAug 26, 2024

    What is cqi?

    • Mads Stoumann
      Mads StoumannAug 26, 2024

      It’s a container-query (the “cq”) unit, for the inline (“i”) dimension. If you use contanter-type: inline-size, then 100cqi is the total width of the container.

  • Graham McMahon
    Graham McMahonAug 26, 2024

    Not bad, but Jupiter is too small relative to Saturn, Uranus and Neptune

    • Rich Winter
      Rich WinterAug 27, 2024

      Well, ditto the sun. And where's the Jupiter spot? And where is the Saturn ring, and, and, and...

    • Mads Stoumann
      Mads StoumannAug 27, 2024

      I know, see the Update 😉

  • Rich Winter
    Rich WinterAug 27, 2024

    It's great that you're providing the defaults in case a browser doesn't understand CSS variables, but I don't that any browser that has that problem would understand cqi. (I could be wrong, but I would think cqi to be to "new')

  • Tanvir Shaikh
    Tanvir ShaikhAug 27, 2024

    This is amazing & very cool.

  • Edson Jr.
    Edson Jr.Aug 27, 2024

    As for learning purpose this article is awesome! Thank you! 👏🏼👏🏼👏🏼👏🏼👏🏼

  • Charles Robertson
    Charles RobertsonAug 27, 2024

    Here is my effort from a few years ago, using GSAP & CSS:

    codepen.io/charles1971/pen/BaNyqYE

    It is only the inner planets 🙂

  • Charles Robertson
    Charles RobertsonAug 27, 2024

    Can you give us the link to the final codepen?

    • Mads Stoumann
      Mads StoumannAug 27, 2024

      It’s the embedded Pen, I didn’t upload a Pen with the AU-version.

      • Charles Robertson
        Charles RobertsonAug 27, 2024

        Hmmm. It’s just that there is no rotation, around the sun, in the embedded pen.
        The planets are only rotating around their centres.
        But maybe that’s because I am viewing it via mobile Safari on an iPhone 8+ [iOS 16.7]

        • Mads Stoumann
          Mads StoumannAug 27, 2024

          Yes, offset-path was added to mobile Safari in iOS 17 😟

          • Charles Robertson
            Charles RobertsonAug 27, 2024

            Well it works on my iPhone here:

            developer.mozilla.org/en-US/docs/W...

            So, it must be something else?

            • Mads Stoumann
              Mads StoumannAug 28, 2024

              Not sure? offset-distance, maybe?

              • Charles Robertson
                Charles RobertsonAug 28, 2024

                That’s the one.
                Indeed, this is not supported, at all, by mobile Safari.

                UPDATE:

                Well, initially, there was a red cross through the safari icon, but I think this must have been related to non mobile Safari, because when I tried the tests at:

                developer.mozilla.org/en-US/docs/W...

                They all worked on my iPhone.

                So, it isn’t that property.

                • Mads Stoumann
                  Mads StoumannAug 28, 2024

                  It works in mobile Safari on my iPhone, iOS 17.5.1 🤷‍♂️

                  • Charles Robertson
                    Charles RobertsonAug 28, 2024

                    OK. It must be something to do with my version of iOS at 16.7?

                    UPDATE:

                    I have a feeling it maybe something to do with the unit cqi.
                    Now it says that it came in in iOS 16, but it might have been 16.8 or something.

                    Whatever is going on, my version doesn’t seem to be understanding the correct location of each planet’s rotational centre, which I guess is the centre of the canvas, where the sun is.

                    Very strange.

                    Maybe I will update my iOS to 16.7.10. This is the highest version I can update to on my iPhone 8+.

                    This is what I see, after I have turned the animation off:

                    Image description

                    • Mads Stoumann
                      Mads StoumannAug 28, 2024

                      Weird, seems like it understands offset-path, but not content-box, which might have been added later to the specs?!

                      • Charles Robertson
                        Charles RobertsonAug 28, 2024

                        Yes. It might be the content-box issue:

                        Image description

                        I have added a value that path-offset understands, and I get this, which is on the right track, but still not right:

                        codepen.io/charles1971/pen/gONjrJa

                        The planets are now all gas giants! 😀

  • Adam
    AdamAug 27, 2024

    2d version == Flatlands! Or… flat spaces?

    Though I will say, toy projects/demos like this are one of the times where using id selectors makes sense, imo. Same net result.

    Great stuff!

  • Syed Muhammad Ali Raza
    Syed Muhammad Ali RazaAug 28, 2024

  • Arsey Kun
    Arsey KunAug 28, 2024

    Mindfully blown, wow. Animators are.....
    A way

  • Beatrice Wambui Mbugua
    Beatrice Wambui MbuguaAug 29, 2024

    This is really cool

  • King Triton
    King TritonAug 29, 2024

    This CSS Solar System demo showcases how simple techniques can create a visually appealing model. Leveraging grid and offset-path is a clever way to achieve smooth animations and responsive design.

  • Nora
    NoraSep 1, 2024

    I especially like how the animation is handled with offset-path, keeping the movement smooth and intuitive. I also created my website using html and css. give it a view and share your suggestions where it needs improvement.

  • MUHAMMED YILMAZ
    MUHAMMED YILMAZSep 10, 2024

    PLUTON!?

  • Agunechemba Ekene
    Agunechemba EkeneNov 18, 2024

    Nice project for my learners!

Add comment