3

I've been playing around with "folding" elements using rotate3d(), and I ran into a problem with half of my fold - during the transition, the z-index isn't respected, but at the end, it pops to the top. I suspect it has something to do with the z part of rotate3d() (similar to here), but it's only happening on one of two elements, and I can't figure out what the difference is.

var button = $('.button');
var open = true;

button.click(() => {
  var right = $('.triangle.topright');
  var left = $('.triangle.topleft');

  if (open) {
    right.addClass('r-close');
    left.addClass('l-close');
  } else {
    right.removeClass('r-close');
    left.removeClass('l-close');
  }

  open = !open;
});
.container {
  box-sizing: border-box;
  display: flex;
  padding: 50px 75px;
  position: relative;
  height: 300px;
  width: 100%;
}

.fold.r-close {
  transform-origin: left;
  transform: rotate3d(0, 1, 0, 90deg);
}

.fold {
  box-sizing: border-box;
  display: inline-block;
  height: 100px;
  width: 100px;
  position: relative;
  transition: all 1.5s;
  transform-style: preserve-3d;
}

.fold.outer {
  width: 150px;
}

.fold.left {
  margin-left: 50px;
}

.triangle {
  height: 0;
  position: absolute;
  transition: all 1.5s;
  width: 0;
}

/* middle */
.triangle.middle {
  top: 0;
  z-index: -1 !important;
}

.triangle.middle.left {
  border-bottom: 100px solid pink;
  border-left: 100px solid transparent;
  right: 0;
}

.triangle.middle.right {
  border-bottom: 100px solid pink;
  border-right: 100px solid transparent;
  left: 0;
}

/* right fold */
.triangle.topright.front {
	border-bottom: 100px solid red;
	border-right: 100px solid transparent;
  backface-visibility: hidden;
  transform: rotate3d(1, 1, 0, 180deg);
}

.triangle.topright.back {
  backface-visibility: hidden;
  border-left: 100px solid transparent;
  border-top: 100px solid pink;
  left: -0.6px;
}

/* left fold */
.triangle.topleft.front {
	border-bottom: 100px solid red;
	border-left: 100px solid transparent;
  backface-visibility: hidden;
  transform: rotate3d(-1, 1, 0, 180deg);
}

.triangle.topleft.back {
  backface-visibility: hidden;
  border-top: 100px solid pink;
  border-right: 100px solid transparent;
  right: -0.6px;
}

/* folds */
.r-close.back {
  transform: rotate3d(1, 1, 0, 180deg);
}

.triangle.r-close.front {
  transform: rotate3d(1, 1, 0, 0deg);
}

.l-close.back {
  transform: rotate3d(-1, 1, 0, 180deg);
}

.triangle.l-close.front {
  transform: rotate3d(-1, 1, 0, 0deg);
}

.button {
  bottom: 0;
  position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="fold outer">
    <div class="triangle middle left"></div>
    <div class="fold left">
      <div class="triangle topleft front"></div>
      <div class="triangle topleft back"></div>
    </div>
  </div>
  <div class="fold outer">
    <div class="triangle middle right"></div>
    <div class="fold right">
      <div class="triangle topright front"></div>
      <div class="triangle topright back"></div>
    </div>
  </div>
  <button class="button">Click</button>
</div>

https://jsfiddle.net/jonkani/p5858nso/

1 Answer 1

1

This behavior is logical, it's a bit difficult to explain but it's due to the direction of the rotation. If you look closely you will see that the right part turn by going to the top (considering the Z axis) but the the left part turn by going to the bottom that why it's hidden while rotating.

In order to correct this, you need to inverse the rotation of the left part to make it behave like the right one. Instead of 0deg you need to use 360deg.

var button = $('.button');
var open = true;

button.click(() => {
  var right = $('.triangle.topright');
  var left = $('.triangle.topleft');

  if (open) {
    right.addClass('r-close');
    left.addClass('l-close');
  } else {
    right.removeClass('r-close');
    left.removeClass('l-close');
  }

  open = !open;
});
.container {
  box-sizing: border-box;
  display: flex;
  padding: 50px;
  position: relative;
  width: 100%;
}

.fold.r-close {
  transform-origin: left;
  transform: rotate3d(0, 1, 0, 90deg);
}

.fold {
  box-sizing: border-box;
  display: inline-block;
  height: 100px;
  width: 100px;
  position: relative;
  transition: all 1.5s;
  transform-style: preserve-3d;
}

.fold.outer {
  width: 150px;
}

.fold.left {
  margin-left: 50px;
}

.triangle {
  height: 0;
  position: absolute;
  transition: all 1.5s;
  width: 0;
}

/* middle */
.triangle.middle {
  top: 0;
  z-index: -1 !important;
}

.triangle.middle.left {
  border-bottom: 100px solid pink;
  border-left: 100px solid transparent;
  right: 0;
}

.triangle.middle.right {
  border-bottom: 100px solid pink;
  border-right: 100px solid transparent;
  left: 0;
}

/* right fold */
.triangle.topright.front {
	border-bottom: 100px solid red;
	border-right: 100px solid transparent;
  backface-visibility: hidden;
  transform: rotate3d(1, 1, 0, 180deg);
}

.triangle.topright.back {
  backface-visibility: hidden;
  border-left: 100px solid transparent;
  border-top: 100px solid pink;
  left: -0.6px;
}

/* left fold */
.triangle.topleft.front {
	border-bottom: 100px solid red;
	border-left: 100px solid transparent;
  backface-visibility: hidden;
  transform: rotate3d(-1, 1, 0, 180deg);
}

.triangle.topleft.back {
  backface-visibility: hidden;
  border-top: 100px solid pink;
  border-right: 100px solid transparent;
  right: -0.6px;
}

/* folds */
.r-close.back {
  transform: rotate3d(1, 1, 0, 180deg);
}

.triangle.r-close.front {
  transform: rotate3d(1, 1, 0, 0deg);
}

.l-close.back {
  transform: rotate3d(-1, 1, 0, 180deg);
}

.triangle.l-close.front {
  transform: rotate3d(-1, 1, 0, 360deg); /*Updated this*/
}

.button {
  bottom: 0;
  position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="fold outer">
    <div class="triangle middle left"></div>
    <div class="fold left">
      <div class="triangle topleft front"></div>
      <div class="triangle topleft back"></div>
    </div>
  </div>
  <div class="fold outer">
    <div class="triangle middle right"></div>
    <div class="fold right">
      <div class="triangle topright front"></div>
      <div class="triangle topright back"></div>
    </div>
  </div>
  <button class="button">Click</button>
</div>

1
  • Cool, that makes sense. Your change combined with removing the transform-style from the fold class got the behavior I wanted. Thanks!
    – John
    Commented May 5, 2018 at 1:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.