[Из песочницы] Параллакс на чистом CSS

В этой статье показывается, как с помощью CSS трансформаций и махинаций с 3d сделать параллакс-эффект на сайте на чистом CSS.Параллакс почти всегда создаётся с помощью JavaScript и, чаще всего, получается ресурсоёмким, из-за вешания листенеров на событие скролла, модификации DOM напрямую и срабатывания ненужных перерисовок и перестановок. Всё это происходит асинхронно с потоком, в котором браузер рендерит страницу, из-за чего скролл начинает подтормаживать, а картинка рваться на части. Более правильные реализации параллакса отслеживают скролл и используют отложенные обновления DOM с помощью requestAnimationFrame. Получается качественной другой результат, но почему бы вообще не избавиться от JavaScript? Перенос параллакс эффекта в CSS спасает от проблем с производительностью и лишних манипуляций, позволяя браузеру самому всё регулировать за счёт аппаратного ускорения. В результате, почти все ресурсоёмкие процессы обрабатываются напрямую браузерным движком. Частота кадров (FPS) остаётся стабильной, а картинка становится плавной. Плюс, можно сразу комбинировать параллакс с другими CSS фишками — media queries или supports. Отзывчивый параллакс — каково?

Смотреть демо

ТеорияПрежде, чем погрузиться в понимание работы этого механизма, создадим необходимую разметку:

И базовые стили: .parallax { perspective: 1 px; 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 (-1 px); } Вся магия происходит в классе parallax. Определение свойств стилей height и perspective установит перспективу элемента в его центре, создав фиксированный 3D вьюпорт. overflow-y: auto позволит контенту внутри элемента нормально скроллиться, при этом потомки элемента будут отрисовываться относительно фиксированной перспективы. В этом и заключается ключ к созданию параллакс эффекта.Далее, класс parallax__layer. Как и следует из имени, он определяет слой контента, к которому будет применен параллакс эффект. Элемент с этим классом выдирается из общего потока контента и позиционируется так, чтобы заполнить свой контейнер.

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

Смотреть демо

Коррекция глубины Так как параллакс эффект создаётся за счёт 3D преобразований, смещение элемента по оси Z имеет побочный эффект — размеры элемента меняются, в зависимости от того, ближе или дальше он к вьюпорту. Чтобы исправить это, нам нужно применять scale () трансформацию, чтобы элемент отрисовывался в своём изначальном размере: .parallax__layer--back { transform: translateZ (-1 px) scale (2); } Коэффицент скейла можно посчитать по формуле 1 + (translateZ * -1) / perspective). Например, если перспектива вьюпорта задана как 1 px и мы смещаем элемент на -2 px по оси Z, то коэффицентом будет scale (3). .parallax__layer--deep { transform: translateZ (-2 px) scale (3); } Смотреть демо с скорректированной глубинойРегулирование скорости слоя Скорость слоя регулируется комбинацией значений перспективы и смещения по Z. Элементы с отрицательными значениями Z будут скроллиться медленнее, чем элементы с положительными значениями. Чем больше разность значения от 0, тем явнее параллакс эффект (т.е. translateZ (-10 px) будет скроллиться медленнее, чем translateZ (-1 px)).Создание разных участков параллакс эффекта Предыдущие примеры демонстрировали базовую технику использования простого контента, но ведь большинство параллакс сайтов делят страницу на разные участки с разными эффектами. Вот как можно реализовать это в нашем методе.Во-первых, нам нужен элемент parallax__group, чтобы сгруппировать наши слои вместе:

для него 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 (700 px, 0, -800 px) rotateY (30deg); } Взгляните на следующий пример и обратите внимание на галочку debug! Смотреть демо с группами.

Поддержка браузеров Firefox, Safari, Opera и Chrome — все поддерживают эти эффекты Firefox работает, но у него есть небольшая проблема с выравниванием. IE пока не поддерживает preserve-3d (на подходе), поэтому параллакс работать не будет. Но это нормально, тк всё равно нужно дизайнить так, чтобы контент был адекватным и без параллакса — Ну, progressive enhancement и всё такое! Статья — перевод (оригинал на blog.keithclark.co.uk — «Pure CSS parallax scrolling websites»)

© Habrahabr.ru