Параллакс-эффект на чистом CSS

Реклама

В этой статье показано, как с помощью CSS-трансформаций, перспективы и небольших хитростей с масштабированием сделать параллакс-эффект на чистом CSS.




Параллакс чаще всего делается на JavaScript, и почти всегда он реализован плохо: отлавливается событиепрокрутка, изменения в DOM вносятся напрямую в обработчике и вызываются лишние перерасчёты и перерисовки. Всё это происходит асинхронно с потоковым рендерингом браузера, в результате чего некоторые кадры пропускаются и эффект выглядит прерывистым. Впрочем, это не так уж страшно —requestAnimationFrame и отложенное обновление DOM позволяют управлять внешним видом сайтов с параллакс-эффектом. Но что если вы могли бы совсем не зависеть от JavaScript?

Перенос параллакс-эффекта на CSS избавит вас от упомянутых проблем и позволит браузеру положиться на аппаратное ускорение — почти всё будет обрабатываться компоновщиком. В результате вы получите согласованную частоту кадров и гладкую прокрутку страницы. Кроме того, можно сочетать этот эффект с другими CSS-приёмами, такими как медиавыражения и поддержка CSS-свойств. Как насчёт отзывчивого параллакс-эффекта?

Теория

Прежде чем говорить о принципе работы, давайте выполним базовую разметку:

<div class=«parallax«>
<div class=«parallax__layer parallax__layer—back«>
</div>
<div class=«parallax__layer parallax__layer—base«>
</div>
</div>

А вот основные стили:

.parallax {
perspective: 1px;
height: 100vh;
overflow-x: hidden;
overflow-y: auto;
}
.parallax__layer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.parallax__layer—base {
transform: translateZ(0);
}
.parallax__layer—back {
transform: translateZ(-1px);
}

Именно класс .parallax содержит всю магию параллакс-эффекта. Указав для элемента свойства height иperspective, мы привяжем построение перспективы от центра этого элемента, создав тем самым исходный фиксированный 3D вьюпорт. Благодаря свойству overflow-y: auto контент внутри элемента будет прокручиваться как обычно, но элементы-потомки теперь будут отображаться относительно фиксированной точки. Это ключевой принцип создания параллакс-эффекта.




Далее — класс .parallax__layer. Как можно понять из названия класса, он определяет слой контента, к которому будет применяться параллакс-эффект; элемент выпадает из основного потока и заполняет собой всё пространство контейнера.

И наконец, у нас есть классы-модификаторы .parallax__layer—base и .parallax__layer—back. Они определяют скорость прокрутки параллакс-элемента посредством перемещения его по оси Z (отодвигая его от вьюпорта или приближая к нему). Для краткости я установил только две скорости слоя — позже добавим ещё.

Коррекция глубины

Поскольку параллакс-эффект создаётся при помощи 3D-трансформаций, сдвиг элемента по оси Z имеет побочный эффект: по мере того, как он приближается к вьюпорту или отодвигается от него, его реальный размер меняется. Чтобы компенсировать это, мы должны применить трансформацию scale() к этому элементу — так он будет отображаться в оригинальном размере:

.parallax__layer—back {
transform: translateZ(-1px) scale(2);
}

Коэффициент масштабирования (scale) можно вычислить с помощью формулы:1 + (translateZ * -1) / perspective. Например, если свойство perspective нашего вьюпорта равно1px, и мы перемещаем элемент по оси Z на -2px, то коэффициент масштабирования будет равен 3:

.parallax__layer—deep {
transform: translateZ(-2px) scale(3);
}

Управление скоростью движения слоя

Скорость движения слоя определяется сочетанием значений перспективы и перемещения по оси Z. Элементы с отрицательным значением translateZ прокручиваются медленнее, чем с положительным. Чем дальше это значение от 0, тем более выраженным получится параллакс-эффект (то есть при translateZ(-10px)прокрутка происходит медленнее, чем при translateZ(-1px)).

Разделы страницы с параллакс-эффектом

Предыдущие примеры демонстрировали основные приёмы, используя очень простой контент, но страницы большинства сайтов состоят из отдельных блоков-разделов, к которым можно применять разные эффекты. Вот как это делается.

Для начала нам понадобится элемент .parallax__group, чтобы сгруппировать наши слои:

<div class=«parallax«>
<div class=«parallax__group«>
<div class=«parallax__layer parallax__layer—back«>
</div>
<div class=«parallax__layer parallax__layer—base«>
</div>
</div>
<div class=«parallax__group«>
</div>
</div>

Вот CSS-стили для группового элемента:

.parallax__group {
position: relative;
height: 100vh;
transformstyle: preserve-3d;
}

В этом примере мне нужно, чтобы каждая группа заполняла вьюпорт, поэтому я указал height: 100vh, однако при необходимости можно указывать разные значения для каждой группы. Значениеtransform-style: preserve-3d не даёт браузеру производить слияние слоёв элементов.parallax__layer, а position: relative позволяет расположить дочерние элементы parallax__layer относительно группового элемента.

При группировке элементов важно помнить одно правило: нельзя обрезать содержимое группы. Если применить свойство overflow: hidden к элементу .parallax__group, параллакс-эффект не будет работать. Если не обрезать контент, элементы-потомки будут выходить за его границы, поэтому придётся проявить изобретательность и использовать разные значения z-index для групп, чтобы обеспечить правильное скрытие/отображение контента при прокрутке документа.

Не существует чётких правил для решения проблемы с позиционированием слоёв — в разных проектах может быть разная реализация. Гораздо проще устранить неполадки в слоях, если понимать, как работает параллакс-эффект — чтобы увидеть картину яснее можно применить трансформацию к групповым элементам:

.parallax__group {
transform: translate3d(700px, 0, -800px) rotateY(30deg);
}

Посмотрите на следующий пример — обратите внимание на опцию debug!

Поддержка браузерами

  • Firefox, Safari, Opera и Chrome поддерживают этот эффект.
  • В Firefox в данный момент присутствует небольшая проблема с выравниванием, хотя в целом всё работает.
  • IE пока не поддерживает свойство preserve-3d (скоро будет), так что параллакс-эффект в этом браузере не работает. Но это не страшно, так как ваш дизайн всё равно должен работать и без параллакс-эффекта — сами знаете: прогрессивное улучшение и всё такое!

Статья взята с сайта: https://htmlacademy.ru