CSS concentric circles with orbiting "planets"

Issue

I’m trying to render a “solar system” diagram only with css, the concentric circles are easy to do with css border-radius, border and some transforms but I’m trying to find a way to have the little “planets” adhere to the “orbits” or colored borders. There has to be a more precise way to achieve this

If you look at this image you will see what I’m trying to do:

enter image description here

And how it currently looks, sorry for inline css…

enter image description here

<div style="width:100%; height:100vh; padding:0px; background-color:white; display:flex; flex-direction:column; position:relative; align-items:flex-end;">
        <div style="width:250px; height:250px; position:absolute; border-radius:50%; background-color:red; top:50%; transform:translateY(-50%) translateX(50%);  right:0px"></div>
        <div style="width:450px; height:450px; position:absolute; border-radius:50%; border:2px solid red; top:50%; transform:translateY(-50%) translateX(50%);  right:0px"></div>
        <div style="width:650px; height:650px; position:absolute; border-radius:50%; border:2px solid red; top:50%; transform:translateY(-50%) translateX(50%);  right:0px"></div>
        <div style="width:850px; height:850px; position:absolute; border-radius:50%; border:2px solid red; top:50%; transform:translateY(-50%) translateX(50%);  right:0px"></div>
        <div style="position:absolute; height:70%; width:100px; top:50%; transform:translateY(-50%); right:15%; outline:1px solid red;">
            <div style="width:25px; height:25px; border-radius:50%; border:1px solid red; position:absolute; top:0px; left:0px;"></div>
            <div style="width:25px; height:25px; border-radius:50%; border:1px solid red; position:absolute; transform:translateY(-50%); top:50%; right:100%;"></div>
            <div style="width:25px; height:25px; border-radius:50%; border:1px solid red; position:absolute; bottom:0px; left:0px;"></div>
        </div>
        <div style="position:absolute; height:80%; width:100px; top:50%; transform:translateY(-50%); right:55%; outline:1px solid red;">
            <div style="width:50px; height:50px; border-radius:50%; border:1px solid red; position:absolute; top:0px; left:0px;"></div>
            <div style="width:50px; height:50px; border-radius:50%; border:1px solid red; position:absolute; transform:translateY(-50%); top:50%; right:100%;"></div>
            <div style="width:50px; height:50px; border-radius:50%; border:1px solid red; position:absolute; bottom:0px; left:0px;"></div>
        </div>
    </div>

Solution

Since it’s about circles you can rely on rotation where you simply need to know the distance from the center (the radius). You can also optimize the concentric circles by using less elements.

Here is an example where I will be using CSS variables to easily control each element. Note that the order of transformation is important (we center using translate, we rotate, then we translate again)

.orbit{
  width:150px;
  height:150px;
  padding:30px;
  border-radius:50%;
  background:red content-box;
  border:1px solid red; /*1st orbit at 105px (30px + 150px/2) */
  margin:auto;
  position:relative;
}
/* 2nd at 135px  */
.orbit:before,
.orbit:after{
   content:"";
   position:absolute;
   top: var(--o,-30px);
   bottom: var(--o,-30px);
   left: var(--o,-30px);
   right: var(--o,-30px);
   border:inherit;
   border-radius:inherit
}
/* 3rd orbit at 165px*/
.orbit:after {
  --o:-60px;
}
.orbit span {
  position:absolute;
  z-index:1;
  height:20px;
  width:20px;
  background:blue;
  border-radius:inherit;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%) rotate(var(--r,0deg)) translateX(var(--d,0px));
}
body {
  margin:0;
  height:100vh;
  display:flex;
}
<div class="orbit">
    <span style="--d:105px;--r:80deg"></span>
    <span style="--d:105px;--r:120deg"></span>
    <span style="--d:105px;--r:-80deg"></span>
    <span style="--d:135px;--r:80deg;height:30px;width:30px;background:green"></span>
    <span style="--d:135px;--r:-90deg;height:30px;width:30px;background:green"></span>
    <span style="--d:165px;--r:-45deg"></span>
    <span style="--d:165px;--r:200deg;height:50px;width:50px;background:purple"></span>
</div>

Another more optimized code without transparency:

.orbit{
  width:150px;
  height:150px;
  padding:30px;
  border-radius:50%;
  background:red content-box;
  border:1px solid red;
  box-shadow:
    0 0 0 29px #fff,
    0 0 0 30px red,
    0 0 0 59px #fff,
    0 0 0 60px red;
  margin:auto;
  position:relative;
}

.orbit span {
  position:absolute;
  height:20px;
  width:20px;
  background:blue;
  border-radius:inherit;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%) rotate(var(--r,0deg)) translateX(var(--d,0px));
}
body {
  margin:0;
  height:100vh;
  display:flex;
}
<div class="orbit">
    <span style="--d:105px;--r:80deg"></span>
    <span style="--d:105px;--r:120deg"></span>
    <span style="--d:105px;--r:-80deg"></span>
    <span style="--d:135px;--r:80deg;height:30px;width:30px;background:green"></span>
    <span style="--d:135px;--r:-90deg;height:30px;width:30px;background:green"></span>
    <span style="--d:165px;--r:-45deg"></span>
    <span style="--d:165px;--r:200deg;height:50px;width:50px;background:purple"></span>
</div>

Answered By – Temani Afif

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published