htmlcss

Making planets follow their orbit in HTML/CSS


So I'm working on a React project for the first time (Only working with HTML and CSS so far). I'm trying to create a solar system where the planets evolve around the sun. For the snippet below I only included the first planet with its orbit so far. The sun is supposed to be centered 50% off screen. I just can't quite figure out how to align the rotation of the planet with the center of the sun. The closest I got to solving the problem was mercury following its orbit for roughly half of the rotation but then drifting off into the second orbit. That is how it currently looks: position 1 position 2

Here is a snippet of my code:

    <span class="sun"></span>
    <span class="mercury"></span>
    <span class="mercury_orbit"></span>

And for App.css:

.sun {
  --sun-left: calc(-10vw); 
  --sun-top: 50%; 
  
  height: 20vw; 
  width: 20vw; 
  position: fixed;
  left: var(--sun-left); 
  top: var(--sun-top);  
  background-color: #f27500;
  border-radius: 50%;  
  display: inline-block;
  transform: translateY(-50%);  
  max-height: 350px;  
  max-width: 350px;   
  min-height: 150px;  
  min-width: 150px;  
}
.mercury {
  position: absolute;
  top: 50%;
  left: var(--sun-left);
  width: 125px;
  height: 125px;
  background-color: rgb(255, 255, 255);
  border-radius: 50%;
  
  transform-origin: -0.5vw;
  
  transform: rotate(0deg) translateX(280px);
  
  animation: orbitMercury 10s linear infinite;
}

@keyframes orbitMercury {
  0% {
    transform: rotate(0deg) translateX(280px);
  }
  100% {
    transform: rotate(360deg) translateX(280px);
  }
}
.mercury_orbit {
  position: fixed; 
  top: 50%; 
  left: calc(-280px); 
  width: 560px; 
  height: 560px; 
  background-color: transparent; 
  border: 1px solid rgb(255, 255, 255); 
  border-radius: 50%; 
  transform: translateY(-50%); 
}

I tried several approaches such as: assigning the sun's position to a variable and using that variable for positioning mercury, use of different units for transform-origin like vw, % and px.


Solution

  • You can translate Mercury -50%, -50% to "center" it, then rotate to the expected angle and translate to the orbital radius.

    Example:

    .mercury {
      --mercury-center: translate(-50%, -50%);
      --mercury-orbit-radius: translateX(280px);
    
      position: absolute;
      top: 50%;
      left: 0;
      width: 125px;
      height: 125px;
      background-color: rgb(255, 255, 255);
      border-radius: 50%;
    
      transform: var(--mercury-center) rotate(0deg) var(--mercury-orbit-radius);
    
      animation: orbitMercury 10s linear infinite;
    }
    
    @keyframes orbitMercury {
      0% {
        transform: var(--mercury-center) rotate(0deg) var(--mercury-orbit-radius);
      }
      100% {
        transform: var(--mercury-center) rotate(360deg) var(--mercury-orbit-radius);
      }
    }
    
    -60 degrees 0 degrees +60 degrees
    position -60 degrees position 0 degrees position 60 degrees