Two divs orbiting around a center CSS animation

Viewed 2451

I am attempting to "orbit" two separate divs in circular motion around a center, however I am having trouble getting the two divs to follow the same circular path in my CSS animation.

.container {
  width: 500px;
  height: 500px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.box {
  background-color: pink;
  width: 100px;
  height: 100px;
  animation: battle 6s linear infinite;
  position: absolute;
  margin: 10px;
}

@keyframes battle {
  from {
    transform: rotate(0deg) translateX(150px) rotate(0deg);
  }
  to {
    transform: rotate(360deg) translateX(150px) rotate(-360deg);
  }
}
<div class="container">
  <div class="box">
  </div>
  <div class="box">
  </div>
</div>

Jsfiddle

2 Answers

Let your parent element be the guide;

When the goal is to rotate in a consistent spacing around a center (as opposed to say an "elliptical orbit" that is more of an oval pattern) than the easiest technique is to provide a parent to set a consistent boundary and attach children within it to use its position as their animation path. The goal is to just supply an illusion of individual elements orbiting in sync when in reality just one is rotating with its default transform-origin of center acting as the guide for the children "orbiting" within it.

In our case we took a parent whose equal circumference is roughly the size of the "orbit desired" and we gave it a border-radius of 50% to create a circle. This makes no point on the element less than or greater distance from the other. We make it a position: relative element so that we can apply position: absolute to any children of it. In this example we use pseudo elements but they could just as easily be additional DOM node elements like divs.

By fixing our children to specific points on the parent we create the equal distance from the X/Y of the parent's transform-origin center we desire and apply the rotate transform to spin the parent. However if we only did that then the children would also follow that path and not keep vertical (as it is assumed is desired) so we simply re-use the same animation applied to the parent but in reverse to offset its rotation. The result is a parent element spinning one direction, and the children in the other to create the effect seen in the example. Hope this helps!

#rotator {
  position: relative;
  width: 7rem;
  height: 7rem;
  animation: rotations 6s linear infinite;
  border: 1px orange dashed;
  border-radius: 50%;
  margin: 3rem;
}

#rotator:before, #rotator:after {
  position: absolute;
  content: '';
  display: block;
  height: 3rem;
  width: 3rem;
  animation: inherit;
  animation-direction: reverse;
}

#rotator:before {
  background-color: red;
  top: -.25rem;
  left: -.25rem;
}

#rotator:after {
  background-color: green;
  bottom: -.25rem;
  right: -.25rem;
}


@keyframes rotations {
  to { transform: rotate(360deg) }
}
<div id="rotator"></div>

Something I did many years ago might be close to what you are looking for:

// Base
body {
  background: #252525;
}


// Keyframes
@keyframes rotateClockwise {
  100% {
    transform: rotate(360deg);
  }
}

@keyframes rotateCounterClockwise {
  100% {
    transform: rotate(-360deg);
  }
}


// Ring
.ring {
  position: relative;
  left: 50%;
  top: 50px;
  margin-left: -100px;
  height: 200px;
  width: 200px;
  border: 10px solid #666;
  border-radius: 50%;
}


// Dots
.dot {
  position: absolute;
  height: 250px;
  width: 40px;
  top: -25px;
  left: 50%;
  margin-left: -20px;
  
  &:before {
    display: block;
    content: '';
    height: 40px;
    width: 40px;
    border-radius: 50%;
    box-shadow: 0 2px 3px rgba(0,0,0,.1);
  }
}

.dot--one {
  animation: rotateClockwise 4s linear infinite;
  
  &:before {
    background: #e6a933;
  }
}

.dot--two {
  animation: rotateCounterClockwise 2s linear infinite;

  &:before {
    background: #e63348;
  }
}

.dot--three {
  animation: rotateClockwise 7s linear infinite;
  
  &:before {
    background: #70b942;
  }
}

.dot--four {
  animation: rotateCounterClockwise 12s linear infinite;
  
  &:before {
    background: #009ee3;
  }
}
<div class="ring">
  <div class="dot dot--one"></div>
  <div class="dot dot--two"></div>
  <div class="dot dot--three"></div>
  <div class="dot dot--four"></div>
</div>

https://codepen.io/seanstopnik/pen/93f9cbcbcf9b38684bfc75f38c9c4db3

Related