Perfecting perspective - css folding effect

702 Views Asked by At

http://codepen.io/stevendavisphoto/pen/xGdQBY

.image {
  width:600px;
  height:200px;
  overflow:hidden;
}
.pane1,
.pane2,
.pane3,
.pane4 {
  height:100%;
  float:left;
  background-image:url('http://img06.deviantart.net/22c0/i/2013/256/a/e/san_francisco_skyline_by_stevendavisphoto-d6m7285.jpg');
  background-size:cover;
}
.pane1 {
  background-position:0 0;
  width:25%;
}
.folder1,
.folder2 {
  height:100%;
  float:left;
  -webkit-backface-visibility:hidden;
  -webkit-transition:all 1s linear;
  -webkit-transform-origin:left center;
}
.folder1 {
  width:50%;
  -webkit-transform: perspective(300px) rotateY(90deg);
}
.image:hover .folder1 {
  -webkit-transform: perspective(300px) rotateY(0deg);
}
.black {
  position:absolute;
  top:0;
  left:0;
  right:50%;
  bottom:0;
  background:black;
  opacity:0.5;
  z-index:99;
  -webkit-backface-visibility:hidden;
  transition:opacity 1s linear;
}
.image:hover .black {
  opacity:0;
}
.pane2 {
  background-position:33.33% 0;
  width:50%;
}
.folder2 {
  width:50%;
  -webkit-transform: perspective(150px) rotateY(-90deg);
}
.image:hover .folder2 {
  -webkit-transform: perspective(150px) rotateY(0deg);
}
.folder2 .black {
  right:0;
}
.pane3 {
  background-position:66.67% 0;
  width:100%;
}
.pane4 {
  background-position:100% 0;
  width:25%;
  -webkit-transition:all 1s linear;
  -webkit-transform:translateX(-200%);
}
.image:hover .pane4 {
  -webkit-transform:translateX(0);
}
<div class="image">
  <div class="pane1"></div>
  <div class="folder1">
    <div class="black"></div>
    <div class="pane2"></div>
    <div class="folder2">
      <div class="black"></div>
      <div class="pane3"></div>
    </div>
  </div>
  <div class="pane4"></div>
</div>

I am trying to make this folding effect perfect. The right side of the "pane3" inner fold is not lining up realistically with the left side of "pane4". Can anyone help me here? I am kinda new to perspective transforms. Thanks!

2

There are 2 best solutions below

0
On

One option is to move folder2 outside of folder1 and transform it independently, rather than trying to do it inside folder1. Rotate folder2 about its right edge instead of the left.

.image {
  width:600px;
  height:200px;
  overflow:hidden;
}
.pane1,
.pane2,
.pane3,
.pane4 {
  height:100%;
  float:left;
  background-image:url('http://img06.deviantart.net/22c0/i/2013/256/a/e/san_francisco_skyline_by_stevendavisphoto-d6m7285.jpg');
  background-size:cover;
}
.pane1 {
  background-position:0 0;
  width:25%;
}
.folder1,
.folder2 {
  height:100%;
  float:left;
  -webkit-backface-visibility:hidden;
  -webkit-transition:all 1s linear;
  -webkit-transform-origin:left center;
}
.folder1 {
  width:25%;
  -webkit-transform: perspective(300px) rotateY(90deg);
}
.image:hover .folder1 {
  -webkit-transform: perspective(300px) rotateY(0deg);
}
.black {
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background:black;
  opacity:0.5;
  z-index:99;
  -webkit-backface-visibility:hidden;
  transition:opacity 1s linear;
}
.image:hover .black {
  opacity:0;
}
.pane2 {
  background-position:33.33% 0;
  width:100%;
}
.folder2 {
  width:25%;
  -webkit-transform-origin: right center;
  -webkit-transform: translateX(-200%) perspective(300px) rotateY(-90deg);
}
.image:hover .folder2 {
  -webkit-transform: translateX(0) perspective(300px) rotateY(0deg);
}
.folder2 .black {
  right:0;
}
.pane3 {
  background-position:66.67% 0;
  width:100%;
}
.pane4 {
  background-position:100% 0;
  width:25%;
  -webkit-transition:all 1s linear;
  -webkit-transform:translateX(-200%);
}
.image:hover .pane4 {
  -webkit-transform:translateX(0);
}
<div class="image">
  <div class="pane1"></div>
  <div class="folder1">
    <div class="black"></div>
    <div class="pane2"></div>
  </div>
  <div class="folder2">
    <div class="black"></div>
    <div class="pane3"></div>
  </div>
  <div class="pane4"></div>
</div>

1
On

It is not a problem of perspective, it's a problem about synchronizing a linear movement (that of the folder4) with the result of 2 rotations.

That would imply a dificult calculus.

Instead, go on with your idea of nesting elements one step beyond, and set folder4 as a child of folder3

In my snippet, I have set the transform in the opposite way, it is easier to see how it works this way.

Also, I have rotated the base, so that you can see in depth that the elements are moving as they should. Just remove the base rotation and set the perspective that you want there.

body {
  perspective: 300px;
  perspective-origin: 300px 100px;
}
.image {
  height: 200px;
  width: 800px;
  position: relative;
  transform: rotateX(40deg);
}

div {
  transform-style: preserve-3d;
  transition: transform 10s;
  transform-origin: left center;
}

.pane1,
.pane2,
.pane3,
.pane4 {
  height:100%;
  width: 200px;
  background-image: url('http://img06.deviantart.net/22c0/i/2013/256/a/e/san_francisco_skyline_by_stevendavisphoto-d6m7285.jpg');
  background-size: 800px;
  position: absolute;
}

.pane2,
.pane3,
.pane4 {
  left: 200px;
}

.pane2 {
  background-position: -200px 0px;
}

.pane3 {
  background-position: -400px 0px;
}

.pane4 {
  background-position: -600px 0px;
}

.image:hover .pane2 {
  transform: rotateY(90deg);
}

.image:hover .pane3 {
  transform: rotateY(-180deg);
}

.image:hover .pane4 {
  transform: rotateY(90deg);
}
<div class="image">
    <div class="pane1">
        <div class="pane2">
            <div class="pane3">
                <div class="pane4"></div>
            </div>
        </div>
    </div>
</div>