Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a box flap open effect using only CSS

I tried to create this effect using transitions. It should look like you are opening a box.

There are 2 problems:

  1. The order in which the box closes is same as in which it opens. Is there anyway to close the box in reverse order of its opening so that the box goes back in the same state it was when closed?
  2. The ends of the green and yellow flaps are hidden during transition because of the red and blue flaps, so it doesn't look 3D. Is there a way I can show all flaps in 3D way?

I would prefer if the solution was in pure CSS , no JavaScript please.

#box {
  position: relative;
  top: 170px;
  left: 170px;
  width: 300px;
  height: 300px;
  border: 1px solid black;
  perspective: 800px;
} 
#flap1, #flap2, #flap3, #flap4 {
  position: absolute;
}
#flap1 {
  background-color: red;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform-origin: 0 0;
  transition: transform 1s;
}
#flap2 {
  left: 150px;
  background-color: blue;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform-origin: 100% 0;
  transition: transform 1s ease 0.3s;
}
#flap3 {
  background-color: green;
  width: 300px;
  height: 150px;
  transform-origin: 0 0;
  transition: transform 1s ease 0.6s;
}
#flap4 {
  background-color: yellow;
  top: 150px;
  width: 300px;
  height: 150px;
  transform-origin: 0 100%;
  transition: transform 1s ease 0.9s;
}
#box:hover #flap1{
  transform: rotateY(-170deg);
}
#box:hover #flap2{
  transform: rotateY(170deg);
}
#box:hover #flap3{
  transform: rotateX(170deg);
}
#box:hover #flap4{
  transform: rotateX(-170deg);
}
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div id="box">
      <div id="flap1"></div>
      <div id="flap2"></div>
      <div id="flap3"></div>
      <div id="flap4"></div>
    </div>
  </body>
</html>
like image 436
Dhruv Chadha Avatar asked May 26 '16 08:05

Dhruv Chadha


People also ask

How do you make a 3D box in CSS?

3D cube effect can be achieved easily with CSS 3D Transform by creating div for each side of the cube. Then use rotateX, rotateY and rotateZ to put them into their places. Transform-origin is also needed to move the rotation fulcrum.

How do you add an animation to an image in CSS?

To create a CSS animation sequence, you style the element you want to animate with the animation property or its sub-properties. This lets you configure the timing, duration, and other details of how the animation sequence should progress.


1 Answers

For Question 1:

If you give the delay in forward order for the :hover selectors and in the reverse order within default selectors, it will achieve the exact reverse animation.

For Question 2:

The fix and the explanation are as follows:

  • For part of the transition duration, the green and yellow boxes don't look like they have 3D effect because there are a couple of elements with higher z-index which is being placed above. This prevents the stretched area (due to perspective rotate) from showing up and thus it looks like it's only 2D (while it actually is not). To overcome this, we need to instruct the browsers to preserve the 3D aspect of the transform. This is done using transform-style: preserve-3d.
  • When we do the above, the flaps will all open with a 3D effect but near the start of the animation and its end, we will see a flicker on the blue flap when the transition actually starts and ends for the blue flap. It seems like this is because the z-index loses effect when 3D transform is used and there is a small amount of time between the losing of the z-index effect and starting of the preserve-3D effect during which the blue flap temporarily goes behind. To address this, the 3D equivalent of z-index: 1 (which is, translateZ(1px)) is added. The translate in Z-axis brings the element closer by 1px to your eye and keeps it above the yellow and green flaps.
  • Finally, despite all the above, there is a small glitch at the end of hover out animation, where the green flap shows through the blue flap. To overcome this, I had changed the delay timings a bit.

(Contrary to what I originally mentioned, the translateZ(0px) is not required and can be removed.)

#box {
  position: relative;
  top: 170px;
  left: 170px;
  width: 300px;
  height: 300px;
  border: 1px solid black;
  perspective: 800px;
  transform-style: preserve-3d;
}
#flap1, #flap2, #flap3, #flap4 {
  position: absolute;
}
#flap1 {
  background-color: red;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform: translateZ(1px);
  transform-origin: 0 0;
  transition: transform 1s 1.5s;
}
#flap2 {
  left: 150px;
  background-color: blue;
  width: 150px;
  height: 300px;
  z-index: 1;
  transform: translateZ(1px);
  transform-origin: 100% 0;
  transition: transform 1s ease 1s;
}
#flap3 {
  background-color: green;
  width: 300px;
  height: 150px;
  transform-origin: 0 0;
  transition: transform 1s ease 0.5s;
}
#flap4 {
  background-color: yellow;
  top: 150px;
  width: 300px;
  height: 150px;
  transform-origin: 0 100%;
  transition: transform 1s ease;
}
#box:hover #flap1 {
  transform: rotateY(-170deg) translateZ(1px);
  transition: transform 1s ease;
}
#box:hover #flap2 {
  transform: rotateY(170deg) translateZ(1px);
  transition: transform 1s ease 0.5s;
}
#box:hover #flap3 {
  transform: rotateX(170deg);
  transition: transform 1s ease 1s;
}
#box:hover #flap4 {
  transform: rotateX(-170deg);
  transition: transform 1s ease 1.5s;
}
<div id="box">
  <div id="flap1"></div>
  <div id="flap2"></div>
  <div id="flap3"></div>
  <div id="flap4"></div>
</div>
like image 86
Harry Avatar answered Nov 15 '22 18:11

Harry