В этой статье показано, как с помощью 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; | |
transform—style: 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