Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS concentric circles with orbiting "planets"

Tags:

css

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>
like image 799
gabogabans Avatar asked Jul 01 '26 05:07

gabogabans


1 Answers

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>
like image 174
Temani Afif Avatar answered Jul 05 '26 18:07

Temani Afif