Современные веб-страницы содержат массу полезной информации, которая отлично себя чувствует на больших мониторах, но ей очень тесно на экранах мобильных устройств. В ответ, дизайнеры начинают создавать интерфейсы, которые работают в очень ограниченном пространстве. Карусели и галереи являются одним из возможных решений этой проблемы, но хотелось сделать более элегантный дизайн. Приход долгожданной посылочки из Китая подсказал мне идею и я решил сделать ее ввиде коробки.
Наш HTML код будет выглядеть так:
<div class="album">
<img src="lee_byeong_heon_center.jpg" alt>
<img class="top" src="lee_byeong_heon_top.jpg" alt>
<img class="left" src="lee_byeong_heon_left.jpg" alt>
<img class="bottom" src="lee_byeong_heon_bottom.jpg" alt>
<img class="right" src="lee_byeong_heon_right.jpg" alt>
</div>
Здесь картинки расположены в обратном порядке, в котором они будут раскрываться: последняя картинка раскроется первой, а затем предпоследняя и так далее. Самая первая картинка, lee_byeong_heon_center.jpg, не будет двигаться вообще.
Теперь настроим стили нашей галереи. Все наши картинки имеют один и тот же размер, но картинки с классами .top
и .bottom
были перевернуты с помощью программы PhotoShop. Теперь нам нужно сделать чтобы элемент-контейнер реагировал на наведение мыши.
.album {
width: 25%;
position: relative;
perspective: 1500px;
-webkit-perspective: 1500px;
margin: 0 auto;
}
Картинки, находящиеся в контейнере, будут масштабироваться в соответствии с его размерами. Теперь напишем CSS-стили для самих изображений:
.album img {
position: absolute;
max-width: 100%;
-webkit-filter: drop-shadow(3px 3px 5px rgba(0,0,0,0.6));
filter: url(shadow.svg#drop-shadow);
filter: drop-shadow(3px 3px 5px rgba(0,0,0,0.6));
transform: rotate3d(0, 0, 0, 0deg);
transition-duration: 1s;
-webkit-transition-duration: 1s;
-o-transition-duration: 1s;
-moz-transition-duration: 1s;
}
Наши изображения абсолютно позиционированы относительно родительского контейнера, имеющего класс album. Анимация изображений будет длиться ровно одну секунду (задается transition-duration
). Изображения также имеют динамически падающие тени, которые в отличие от стандартного свойства box-shadow
, будут в Chrome, Safari и Firefox точно показывать вид тени, при любом положении изображения в 3D пространстве.
Для трехмерного вращения элементов используем свойство transform: rotate3d(x, y, z, deg);
. Первые три параметра определяют, вокруг какой из осей координат будет вращаться объект, а последний – на сколько градусов. X, Y и Z задаются не как абсолютные величины, а как соотношение углов. Например, код transform: rotate3d(2, 1, 0, 90deg);
заставит объект повернуться на 90 градусов вокруг оси X и на 45 (90 * 1 / 2) градусов вокруг Y. То же самое сделает и строчка transform: rotate3d(90, 45, 0, 90deg)
. Чтобы было более понятно, на рисунке ниже я проиллюстрировал вращение блоков вокруг осей: серым прямоугольником показано исходное положение блока, красным выделена ось, вокруг которой происходит вращение. Красный и зеленый прямоугольники показывают какое положение займет блок при повороте на -60 и 60 градусов соответственно.
Одна из главных проблем создания анимаций CSS для Webkit заключается в том, что элементы мгновенно перемещаются из предполагаемой дефолтной позиции в изначальную точку перехода при загрузке станицы, особенно если для свойства transition
установлено значение all
. Применив position: absolute
и обнулив все значения rotate3d
, мы сможем избежать этой ошибки в Chrome и Safari.
Изображения разворачиваются, когда пользователь наводит курсор на контейнер div
. Давайте внимательно посмотрим на CSS код для первого изображения:
.album .right {
transform-origin: right top 0;
-webkit-transform-origin: right top 0; /* Для Safari, Chrome */
-moz-transform-origin: right top 0; /* Для Firefox */
-o-transform-origin: right top 0; /* Для Opera */
-ms-transform-origin: right top 0; /* Для IE */
transition-delay: 3s;
}
.album:hover .right {
transform: rotate3d(0,1,0,180deg);
-moz-transform: rotate3d(0,1,0,180deg); /* Для Firefox */
-ms-transform: rotate3d(0,1,0,180deg); /* Для IE */
-webkit-transform: rotate3d(0,1,0,180deg); /* Для Safari, Chrome */
-o-transform: rotate3d(0,1,0,180deg); /* Для Opera */
transition-delay: 0s;
}
Любое преобразование картинки, находящейся справа, будет исходить в ее правом верхнем углу. Как раз там, где проходит место сгиба нашей коробки. Изображение будет разворачиваться на 180 градусов в Y оси тот момент, когда пользователь наведет мышку на наш контейнер с фотографиями.
Итак, мы рассмотрели стандартное поведение для простых 3D преобразований. Однако если оставить код как есть, изображения будут складываться в том же порядке, в котором они открывались, а мы этого не хотим: нам нужно чтобы изображение, которое развернулось первым, закрылось обратно последним, когда пользователь покидает наш блок DIV
.
Чтобы создать такое поведение, я добавил задержку в начальное состояние для изображения. Помните, что transition-delay
всегда отностится следующиму состоянию. На первый взгляд это может показаться непонятным, поэтому я нарисовал вам следующую табличку:
Задержка |
Задержка перед движением |
Длительность |
Раскладывается (исходное состояние → при наведении курсора) |
Нет (получается из значения при :hover состоянии) |
1 сек. |
Складывается (при наведении курсора → исходное состояние) |
3 сек. (получается из значения при дефолтном состоянии) |
1 сек. |
Остальной код CSS создается по тому же принципу: transition-delay
перед началом анимационного перехода увеличивается при наведении на изображения, которые раскрываются в порядке их расположения, и уменьшается для их первоначального состояния (благодаря чему они закрываются в обратном порядке).
.album .bottom {transform-origin: center bottom; transition-delay: 2.5s;}
.album:hover i.bottom {transform: rotate3d(1, 0, 0, -178deg); transition-delay: .5s;}
.album .left {transform-origin: left top; transition-delay: 2s;}
.album:hover .left {transform: rotate3d(0, 1, 0, -178deg); transition-delay: 1s;}
.album .top {transform-origin: top center; transition-delay: 1.5s;}
.album:hover .top {transform: rotate3d(1, 0, 0, 179deg); transition-delay: 1.5s;}
Я использовал значения менее ± 180° для поворота изображений в связи с тем, что браузеры иногда бывают озадачены: следует ли элементы поворачивать по часовой стрелке или против. Моя маленькая хитрость позволит развернуть изображения так, как нам нужно.
Представленный выше код все еще далек от совершенства; мобильные гаджеты будут интерпретировать первое нажатие на div как выделение и разворачивать изображения, не возвращая их на место: этот код я приберегу для следующей статьи. Я также не стал добавлять запасной вариант для старых браузеров.