Создание эффекта открывания окна с помощью только CSS

Я попытался создать этот эффект с помощью переходов. Это должно выглядеть так, будто вы открываете коробку.

Есть 2 проблемы:

  • Порядок, в котором окно закрывается, совпадает с порядком, в котором он открывается. Стоит ли закрывать коробку в обратном порядке ее открытия, чтобы окно возвращалось в том же состоянии, когда оно было закрыто?
  • Концы зеленых и желтых лоскутов скрыты во время перехода из-за красных и синих лоскутов, поэтому он не выглядит 3D. Есть ли способ показать все закрылки в 3D-режиме?

Я бы предпочел, чтобы решение было в чистом CSS, без JavaScript.

#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>

Ответ 1

Для вопроса 1:

Если вы дадите задержку в прямом порядке для селекторов :hover и в обратном порядке в селекторах по умолчанию, она достигнет точной обратной анимации.

Для вопроса 2:

Исправление и объяснение следующие:

  • Для части продолжительности перехода зеленые и желтые поля не выглядят так, как будто они имеют 3D-эффект, потому что есть пара элементов с более высоким z-index, который помещается выше. Это предотвращает показ растянутой области (из-за поворота перспективы) и, следовательно, она выглядит только 2D (в то время как на самом деле это не так). Чтобы преодолеть это, нам нужно указать браузерам сохранить 3D-аспект преобразования. Это делается с помощью transform-style: preserve-3d.
  • Когда мы сделаем все выше, закрылки откроются с 3D-эффектом, но рядом с началом анимации и ее концом мы увидим мерцание на синей лоскуте, когда переход действительно начнется и закончится для синего лоскута. Похоже, это потому, что эффект z-index теряет эффект при использовании 3D-преобразования, и между потерями эффекта z-index и началом эффекта preserve-3D происходит небольшое количество времени, в течение которого синий лоскут временно отстает, Для этого добавляется трехмерный эквивалент z-index: 1 (который есть, translateZ(1px)). Перемещение по оси Z приближает элемент на 1px к вашему глазу и удерживает его выше желтых и зеленых клапанов.
  • Наконец, несмотря на все вышесказанное, есть небольшой сбой в конце анимации анимации, где зеленый заслон показывает синий лоскут. Чтобы преодолеть это, я немного изменил тайминги задержки.

(В отличие от того, что я изначально упоминал, translateZ(0px) не требуется и может быть удален.)

#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>