9

I'm trying to make a 'dot' orbit around another object (circle) but due to the z-index the dot always appears above the circle it is meant orbiting around.

CodePen link: https://codepen.io/moy/pen/ROVZXd?editors=1100

Ideally the 2nd half of the animation would take place behind the object so it's not seen until it comes out the other side - is that possible?

I thought about fading out the object that is moving around but I don't think that would give a smooth/masked effect?

A bit stuck as to how I'd mask this area as I can't see a way the CSS would know it's meant to be hidden. I thought maybe I could change the z-index 50% though the animation it and reset it at 0%/100% but that doesn't appear to do anything.

Any ideas? Thanks in advance!

.earth {
  background: white;
  border: 1px solid black;
  border-radius: 50%;
  display: block;
  height: 100px;
  margin: 30px auto;
  position: relative;
  width: 100px;
  z-index: 20;
}

.orbit {
  border: 2px #eee transparent;
  border-radius: 50%;
  height: 140px;
  margin: auto;
  position: absolute;
  top: -20px;
  left: -20px;
  transform: rotateZ(60deg) rotateY(60deg);
  transform-style: preserve-3d;
  width: 140px;
  z-index: 10;
}
.orbit .moon {
  animation: move ease-in-out infinite;
  animation-duration: 2s;
  background: black;
  border-radius: 50%;
  height: 15px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 15px;
  z-index: 10;
}

@keyframes move {
  0% {
    transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg); z-index: 20;
  }
  50% {
    z-index: -20;
  }
  100% {
    transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg); z-index: 20;
  }
}
<div class="earth">
  <div class="orbit">
    <div class="moon"></div>
  </div>
</div>
user1406440
  • 1,329
  • 2
  • 24
  • 59
  • 2
    http://www.independent-software.com/deconstructing-css-3-making-of-css3-solar-system-animation-3d-transformations.html – Nandita Sharma Apr 11 '19 at 11:00
  • The problem is present in the stack snippet but not in the codepen link - is the codepen yours or something you're trying to replicate? – Lewis Apr 11 '19 at 11:10
  • I've actually continued playing around with it and added a `z-index` to its parent at 100% which has sorted it I think. Thought I'm not sure why applying the negative `z-index` at 50% didn't work and 100% did as it kinda does just need to be set halfway through! – user1406440 Apr 11 '19 at 11:20

3 Answers3

2

I seem to have solved this by adding a negative z-index to an animation applied to the parent .orbit

Link: https://codepen.io/moy/pen/wZdpRw?editors=1100

I initially applied this at 50% through the animation as that should be the furthest away the dot is before it comes back behind the larger circle. However this didn't work, setting it on 100% did work. Not entirely sure why but it seems to work!

user1406440
  • 1,329
  • 2
  • 24
  • 59
1

The initial issue was due to the fact that you are applying z-index to the parent element and doing so it will impossible to make the child to move behind it (Why elements with any z-index value can never cover its child?) thus changin z-index is useless

Even if you remove the z-index from the parent you still have the transform that is also creating a stacking context making impossible to the child element to move behind so you cannot make the .moon to move behind the .earth.

The only way to do it (like you already noticed) is to remove z-index from the .earth to avoid the earth creating a stacking context and animate z-index of orbit to make the orbit AND the moon moving behind the earth (not only the moon).

Add some coloration to better see this:

.earth {
  background: white;
  border: 1px solid black;
  border-radius: 50%;
  display: block;
  height: 100px;
  margin: 60px auto;
  position: relative;
  width: 100px;
}

.orbit {
  animation: hide ease-in-out infinite;
  animation-duration: 2s;
  background:red;
  border-radius: 50%;
  height: 140px;
  margin: auto;
  position: absolute;
  top: -20px;
  left: -20px;
  transform: rotateZ(60deg) rotateY(60deg);
  transform-style: preserve-3d;
  width: 140px;
}

.orbit .moon {
  animation: move ease-in-out infinite;
  animation-duration: 2s;
  background: black;
  border-radius: 50%;
  height: 15px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 15px;
}

@keyframes move {
  0% {
    transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg);
  }
  100% {
    transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg);
  }
}

@keyframes hide {
  0% {
    z-index: 20;
  }
  100% {
    z-index: -20;
  }
}
<div class="earth">
  <div class="orbit">
    <div class="moon"></div>
  </div>
</div>

Now if you add back z-index to earth it will stop working because of the stacking context:

.earth {
  background: white;
  border: 1px solid black;
  border-radius: 50%;
  display: block;
  height: 100px;
  margin: 60px auto;
  position: relative;
  width: 100px;
  z-index:2;
}

.orbit {
  animation: hide ease-in-out infinite;
  animation-duration: 2s;
  background:red;
  border-radius: 50%;
  height: 140px;
  margin: auto;
  position: absolute;
  top: -20px;
  left: -20px;
  transform: rotateZ(60deg) rotateY(60deg);
  transform-style: preserve-3d;
  width: 140px;
}

.orbit .moon {
  animation: move ease-in-out infinite;
  animation-duration: 2s;
  background: black;
  border-radius: 50%;
  height: 15px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 15px;
}

@keyframes move {
  0% {
    transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg);
  }
  100% {
    transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg);
  }
}

@keyframes hide {
  0% {
    z-index: 20;
  }
  100% {
    z-index: -20;
  }
}
<div class="earth">
  <div class="orbit">
    <div class="moon"></div>
  </div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

You can try key-framing the opacity:

.earth {
  background: white;
  border: 1px solid black;
  border-radius: 50%;
  display: block;
  height: 100px;
  margin: 30px auto;
  position: relative;
  width: 100px;
  z-index: 20;
}

.orbit {
  border: 2px #eee transparent;
  border-radius: 50%;
  height: 140px;
  margin: auto;
  position: absolute;
  top: -20px;
  left: -20px;
  transform: rotateZ(60deg) rotateY(60deg);
  transform-style: preserve-3d;
  width: 140px;
  z-index: 10;
}
.orbit .moon {
  animation: move ease-in-out infinite;
  animation-duration: 2s;
  background: black;
  border-radius: 50%;
  height: 15px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 15px;
  z-index: 10;
}

@keyframes move {
  0% {
    transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg); opacity: 1;
  }
  56% {
    opacity: 1;
  }
  58% {
    opacity: 0;
  }
  77% {
    opacity: 0;
  }
  78% {
  opacity: 1;
  }
  100% {
    transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg); opacity: 1;
  }
}
<div class="earth">
  <div class="orbit">
    <div class="moon"></div>
  </div>
</div>
glhr
  • 4,439
  • 1
  • 15
  • 26
  • Close, but there's a rather sharp pop-in and pop-out on either end. Key-framing the opacity won't allow the circle to disappear right to left, and re-appear right to left as it needs to. – Lewis Apr 11 '19 at 11:15
  • I think I've managed to solve this by adding a negative `z-index` in a separate animation: https://codepen.io/moy/pen/wZdpRw?editors=1100 - seems to work! But not sure why applying it at 100% and not 50% worked! – user1406440 Apr 11 '19 at 11:21
  • I actually saved over the version in the original post so just undone it and forked to an updated version. That link work now? – user1406440 Apr 11 '19 at 11:25
  • Yes it does. Looks great! – glhr Apr 11 '19 at 11:28