Как написать параллакс

#Руководства

  • 23 июн 2020

  • 12

JavaScript добавляет на страницы сайта очень интересные эффекты. Один из них — параллакс. Разбираемся, что это и как его создать самостоятельно.

vlada_maestro / shutterstock

Евгений Кучерявый

Пишет о программировании, в свободное время создаёт игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Параллакс — это иллюзия движения объекта относительно фона, которая появляется, если движется наблюдатель. Такой эффект легко увидеть, если поднести к лицу палец и посмотреть на него сперва одним глазом, а потом вторым.

В этой статье мы рассмотрим, как создать движущиеся фон и другие элементы для сайта на JavaScript.

Исходный код вы найдёте на GitHub.

Для начала подготовим два изображения, которые нам нужны, — передний и задний планы. Для заднего плана я взял фотографию космоса:

Для переднего плана вырезал простой пейзаж с другой фотографии:

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

<div class="parallax background-space" id="background-space"></div>
<div class="parallax background-tree" id="background-tree"></div>

Альтернативный вариант: установить один из фонов для body, а второй для wrapper — адаптируйте код под свой проект. Далее добавляем стили:

.parallax
{
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
}
 
.background-space
{
   background: url(../images/space.png);
   background-size: 100% 100%;
   z-index: 1;
}
 
.background-tree
{
   background: url(../images/tree.png);
   background-size: 105% 105%;
   z-index: 2;
   filter: blur(1px);
}

У элементов фиксированная позиция на странице — один элемент (дерево) расположен поверх другого (космос). Также мы добавили фильтр размытости для дерева, чтобы скрыть неровности и создать ощущение расфокуса.

Остаётся написать скрипт:

//Получаем элемент фона с деревом
const bgTree = document.getElementById("background-tree");
 
//При движении мышью вызываем функцию, которая меняет положение фона
document.addEventListener("mousemove", function (e) { MoveBackground(e); });
 
function MoveBackground(e)
{
   //Рассчитываем, насколько далеко от начала оси находится курсор: 0 - 0, 0.5 - середина экрана, 1 - ширина экрана (например, 1920)
   //Затем умножаем получившееся число на 30 - настолько будет сдвигаться фон
   //Например, если курсор находится посередине страницы (0.5), то при умножении получится 15
   //Далее отнимаем половину от 30, чтобы фон мог двигаться как влево, так и вправо
   let offsetX = (e.clientX / window.innerWidth * 30) - 15;
   let offsetY = (e.clientY / window.innerHeight * 10) - 5;
 
   //Меняем положение фона
   bgTree.setAttribute("style", "background-position: " + offsetX + "px " + offsetY + "px;");
}

Теперь посмотрим на результат:

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

Параллакс работает не только для фона, но и для передних планов.
Что-то подобное любят использовать в Apple на своих лендингах.

Мы добавим на страницу частицы, которые окажутся над основным контентом и будут двигаться вместе с прокруткой страницы.

Для начала нужен блок, куда мы поместим частицы:

<div class="particles" id="particles"></div>

Сам блок не виден пользователю — он нужен нам как контейнер. Теперь подготовим стили:

.particles
{
   position: absolute;
   left: -9999999px;
}
 
.particle
{
   position: fixed;
   top: 0;
   left: 0;
   border-radius: 50%;
   display: block;
   width: 100px;
   height: 100px;
   filter: blur(0px);
   z-index: 1;
   box-shadow: 0 0 10px rgba(0,0,0,0.5);
}

Основные свойства частицам задаём с помощью скрипта.

//Создаём класс для частиц
class Particle
{
   //Конструктор принимает положение частицы по трём осям и цвет
   constructor(x, y, z, color)
   {
       this.x = x;
       this.y = y;
       this.z = z;
 
       //Размытие и скорость зависят от положения частицы по оси Z
       //Чем выше частица, тем более размытой она будет и тем быстрее она будет двигаться
       let blurs = [ 0, 2, 1, 0 ];
 
       this.blur = blurs[z];
       this.speed = z;
       this.color = color;
   }
 
   //Метод движения частицы
   Move(d)
   {
       this.y += this.speed * d;
   }
}
 
//Позиция полосы прокрутки
let scrollPosition = 0;
 
//Получаем контейнер для частиц
const particlesContainer = document.getElementById("particles");
 
//Создаём массив с частицами
const particles =
[
   new Particle(1650, 450, 3, "#FF7019"),
   new Particle(1700, 450, 1, "#FF7019"),
   new Particle(220, 500, 3, "#FF7019"),
   new Particle(600, 700, 1, "#FF7019"),
   new Particle(900, 600, 4, "#FF7019"),
   new Particle(1200, 900, 2, "#FF7019"),
];
 
//Это функция вывода частицы на страницу
Fill();
 
//При каждой прокрутке вызываем функцию Scroll(), которая двигает частицы
window.addEventListener("scroll", function (e) { Scroll(e); });
 
function Scroll(e)
{
   //Определяем, в каком направлении была прокрутка
   let d = 0;
 
   if(window.pageYOffset > scrollPosition)
   {
       d = 1;
   }
   else
   {
       d = -1;
   }
  
   scrollPosition = window.pageYOffset;
 
   //Двигаем все частицы в заданном направлении
   for(let i = 0; i < particles.length; i++)
   {
       particles[i].Move(d);
   }
 
   //Выводим всё на страницу
   Fill();
}
 
function Fill()
{
   //Очищаем контейнер
   particlesContainer.innerHTML = "";
 
   //Создаём новые элементы с обновлёнными свойствами и помещаем их в контейнер
   for(let i = 0; i < particles.length; i++)
   {
       let div = document.createElement("div");
       div.className = "particle";
 
       div.setAttribute("style", "top: " + particles[i].y + "px; left: " + particles[i].x + "px; z-index: " + particles[i].z + "px; filter: blur(" + particles[i].blur + "px); background: " + particles[i].color + "; ");
       particlesContainer.appendChild(div);
   }
}

Теперь можно посмотреть, как это работает:

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

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

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

Участвовать

Научитесь: Профессия Frontend-разработчик
Узнать больше

Скачать шаблон простого сайта на HTML

Если вы хотите, чтобы сайт вызывал «вау-эффект», а ссылками на него делились, используйте параллакс. С ним сайты выглядят объёмно, а элементы могут плавно перемещаться при прокрутке страницы или движении курсора.

В этой статье мы покажем, как сделать параллакс на чистом CSS и JavaScript, поговорим про некоторые JS-библиотеки и посмотрим, как оптимизировать анимацию.

Пример параллакса на CSS

Пример параллакса на CSS. Outer Studio, источник

На чём делать параллакс-эффект: CSS или JavaScript

Параллакс при прокрутке страниц создают с помощью 3D трансформаций: transform-style: preserve-3d, perspective, transform: translateZ и других.

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

А вот параллакс по движению мыши создаётся на JavaScript. В CSS пока нет подходящих для этого свойств, но с его помощью можно оптимизировать параллакс-эффект.

Как сделать параллакс на чистом CSS

Как задать элементу глубину

Чтобы задать элементу глубину, нужно применить к нему transform: translateZ; и указать значение свойства perspective.

Разработчики позиционируют элементы на странице по двум осям: Х и Y, по вертикали и горизонтали. Но есть и третья ось — Z, которая отражает глубину элемента и его расстояние до пользователя. Если просто сдвинуть элемент по этой оси, задав ему свойство transform: translateZ, то мы не увидим разницы. Элемент пока находится в двухмерной плоскости, ведь экран смартфона или монитор ноутбука не обладают глубиной.

Сделать плоскость трёхмерной можно с помощью CSS-свойства perspective. В качестве значения оно принимает расстояние от элемента до пользователя по оси Z — чем больше это значение, тем дальше элемент от вас находится, и наоборот. Часто для perspective указывают значение в 1px — этого достаточно, чтобы установить глубину перспективы.

Пример параллакса на чистом CSS

Сделаем параллакс при прокрутке страницы. Сначала подготовим разметку блока с параллаксом. Добавляем <div> — родитель с классом parallax. Внутри него создаём два элемента-слоя с классами parallax-layer. Первый элемент — <div> с изображением, второй — <span> с текстом. Указываем для <div> дополнительный класс parallax-image, а для <span>parallax-text.

<div class="wrapper parallax">
  <div class="parallax-layer parallax-image">
    <img src="<https://i.pinimg.com/originals/9e/20/fc/9e20fc9ba2e1456ff29caa6780521cb7.jpg>" alt="Сад изящных слов">
  </div>
  <span class="parallax-layer parallax-text">Сад изящных слов</span>
</div>

Задаём <div>-родителю свойство perspective: 1px. Оно создаёт виртуальную 3D-плоскость, указывая, что центр блока parallax — исходная точка построения перспективы. Добавляем overflow-y: auto, чтобы прокручивать элементы-потомки относительно фиксированной точки.

.parallax {
  perspective: 1px;
  height: 100vh;
  overflow-y: auto;
}

Теперь удаляем внутренние элементы с классом parallax-layer из общего потока и растягиваем на всю площадь родителя.

.parallax-layer {
  position: absolute;
  inset: 0; // вместо top, bottom, left, right: 0;
}

Остаётся задать смещение по оси Z. Текст будет дальше от пользователя, а фон ближе — за счёт этого мы создадим параллакс-эффект.

.parallax-image {
  transform: translateZ(0);
}

.parallax-text {
  transform: translateZ(-2px);
}

Добавим стили и получим результат:

See the Pen
Untitled by Mikhail (@smfms)
on CodePen.

Посмотреть на CodePen

Если открыть вкладку с CSS, можно заметить, что для блока parallax-text задан scale(3) — то есть элемент увеличен в три раза. Зачем мы это сделали?

Дело в том, что элемент, отдаляясь от нас в 3D-плоскости, визуально уменьшается в размерах. И наоборот, приближаясь — увеличивается. Чтобы компенсировать эти изменения, мы используем scale. А его значение вычисляем по формуле:

1 + (translateZ * −1) / perspective

В нашем случае вычисление будет таким:

1 + (-2 * −1) / −1

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

See the Pen
Sass parallax example by Scott Kellum (@scottkellum)
on CodePen.

Пример параллакса с множеством элементов. Автор — Скотт Келлум, CodePen

Как сделать параллакс на JavaScript

Теперь создадим параллакс-эффект на JavaScript: сделаем карточку с несколькими элементами, которые будут смещаться при движении курсора — каждый со своей скоростью. Так как элементы смещаются по осям X и Y, это будет 2D-параллакс.

Для начала напишем разметку, похожую на ту, что мы использовали в прошлом примере. Нам нужны <div>-обёртка и внутренние анимируемые элементы:

<div class="parallax">
  <div class="parallax__inner">
    <h1 class="parallax__layer title">
      Здорово быть енотом!
    </h1>
        
    <button class="parallax__layer button" type="button">
	 Стать енотом
    </button>
        
    <div class="parallax__layer circle"></div>
  </div>
</div>

Стили:

.parallax__inner {
  position: relative;
  overflow: hidden;
}

.parallax__layer {
  transition: transform 0.3s linear;
}

Уже сейчас можно задать характер анимации при смещении элементов, указав свойство transition для элементов параллакса. Для более точной настройки можно использовать кривые Безье. Но не рекомендуем использовать значение ease-in-out: могут появиться «рывки» при быстром движении курсора, ведь функция не обладает достаточной линейностью.

 Пример «рывков» при быстром перемещении курсора

Пример «рывков» при быстром перемещении курсора

Перейдём к JavaScript. Найдём параллакс-родитель и все параллакс-элементы, а затем добавим обработчик на родитель. Будем слушать движение курсора мыши — mousemove.

const wrapper = document.querySelector('.parallax__inner');
const layers = document.querySelectorAll('.parallax__layer');

wrapper.addEventListener('mousemove', initParallax);

Опишем функцию initParallax, в которой будем вести расчёты. Далее декомпозируем задачу: сначала найдём координаты курсора относительно карточки, а затем вычислим новые координаты для элементов при срабатывании события мыши.

Всегда вычисляйте координаты относительно того блока, на котором слушается событие мыши — тогда расчёты будут точными. Если вычислять координаты курсора относительно вьюпорта, то смещение параллакс-элементов будет рассчитываться неправильно, так как пропорции вьюпорта и карточки, скорее всего, не будут совпадать.

Сначала вычислим координаты. В JS нет метода, который возвращал бы координаты курсора относительно нужного блока. Свойство clientX возвращает положение по оси X относительно начала вьюпорта. Чтобы начало блока parallax совпадало с 0 по оси X, надо из положения относительно экрана вычесть левый отступ блока parallax. В этом нам поможет метод getBoundingClientRect().

Перейдём к вычислениям. Для удобства записываем текущую координату в переменную и следом добавляем переменную parallaxLeftOffset с внешним отступом блока wrapper от границ экрана. Будем вычитать отступ из текущей позиции курсора и записывать это в переменную coordX:

const initParallax = (evt) => {
  const clientX = evt.clientX;
  const clientY = evt.clientY;

  const parallaxLeftOffset = wrapper.getBoundingClientRect().left;
  const coordX = clientX - parallaxLeftOffset;
  const coordY = clientY - parallaxTopOffset;
}

Теперь левая граница параллакс-блока совпадает с координатой 0. Это не совсем правильно, ведь мы можем отслеживать изменения курсора только вправо. Нужно сделать так, чтобы центр блока совпадал с координатой 0. Для этого дополнительно вычтем половину ширины блока.

const coordX = clientX - parallaxLeftOffset - (0.5 * wrapper.offsetWidth);
const coordX = clientY - parallaxTopOffset - (0.5 * wrapper.offsetHeight);

Чтобы получить ширину, используем свойство offsetWidth. Теперь центр враппера — точка с координатами 0.0. Можно двигаться к самому интересному.

Мы вычислили положение курсора относительно параллакс-блока. Теперь мы можем рассчитать смещение его элементов и задать им его:

layers.forEach((layer)=>{
  const x = (coordX).toFixed(2);
  const y = (coordY).toFixed(2);
  layer.setAttribute('style', `transform: translate(${x}px, ${y}px);`)
});

Округляем координату с помощью метода toFixed и задаём каждому элементу трансформацию по обеим осям. Вот что получилось:

See the Pen
Untitled by Mikhail (@smfms)
on CodePen.

Посмотреть на CodePen

Теперь элементы следуют за курсором. Добавляем коэффициент скорости, который будет замедлять трансформацию элементов. Пусть он будет равен 0.5 — слишком большое значение лучше не устанавливать, так как трансформация должна быть плавной.

Будем умножать вычисленную координату на этот коэффициент.

See the Pen
Untitled by Mikhail (@smfms)
on CodePen.

Код работает, но мы забыли о сути параллакса. Параллакс — это смещение элементов с разной скоростью, а сейчас все элементы двигаются с одинаковой.

Изменим это. Коэффициент скорости будем хранить прямо в разметке в data-атрибуте, так как это удобно.

<div class="parallax">
  <div class="parallax__inner">
    <h1 class="parallax__layer title" data-speed="0.03">
      Здорово быть енотом!
    </h1>
        
    <button class="parallax__layer button" type="button" data-speed="0.05">
      Стать енотом
    </button>
        
    <div class="parallax__layer circle" data-speed="0.18"></div>
  </div>
</div>

Значение не должно быть слишком большим, чтобы элементы двигались плавно. Допишем скрипт с поправкой на скорость:

layers.forEach((layer)=>{
    const layerSpeed = layer.dataset.speed;
    const x = (coordX * layerSpeed).toFixed(2);
    const y = (coordY * layerSpeed).toFixed(2);
    layer.setAttribute('style', `transform: translate(${x}px, ${y}px);`)
});

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

See the Pen
Untitled by Mikhail (@smfms)
on CodePen.

Посмотреть на CodePen

Как оптимизировать параллакс

В начале статьи мы упомянули, что параллакс ресурсозатратен для браузера — на каждое движение мыши вызывается несколько команд по перерасчёту координат. Что можно с этим сделать?

Не смещайте элементы с помощью свойств top, left, right, bottom. Вместо них лучше использовать transform: translateX, translateY — они снижают нагрузку на графический процессор.

В CSS есть свойство will-change. Если задать ему значение transform, то браузер ещё до анимирования выполнит оптимизации. Это снизит нагрузку на графический процессор, и анимация будет работать плавнее, без рывков.

Теоретически, можно использовать декоратор throttle на событии мыши. Но чаще всего у вас будут появляться нежелательные рывки при трансформации. Поэтому задавать задержку стоит с осторожностью.

Заключение

Мы показали простые способы создания параллакса на CSS и JS, но иногда нужны более сложные эффекты. Для таких случаев есть специальные библиотеки, например, Loco Scroll, parallax JS или rellax. С их помощью можно управлять направлением движения элементов, фиксировать слайды при прокрутке, создавать эффект «спешки» или «задержки» анимации.

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

Узнать больше

  • Зачем нужны анимации в вебе и как их создавать
  • Как сделать интерактивную SVG-диаграмму

Время на прочтение
4 мин

Количество просмотров 164K

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

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

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

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

Теория

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

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

И базовые стили:

.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);
}

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

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

Смотреть демо с скорректированной глубиной

Регулирование скорости слоя

Скорость слоя регулируется комбинацией значений перспективы и смещения по Z. Элементы с отрицательными значениями Z будут скроллиться медленнее, чем элементы с положительными значениями. Чем больше разность значения от 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 (на подходе), поэтому параллакс работать не будет. Но это нормально, тк всё равно нужно дизайнить так, чтобы контент был адекватным и без параллакса – Ну, progressive enhancement и всё такое!

Статья — перевод (оригинал на blog.keithclark.co.uk — «Pure CSS parallax scrolling websites»)

Параллакс — это эффект, который создаёт иллюзию глубины. Например, когда вы едете в поезде и смотрите в окно, столбы проносятся мимо вас быстро, деревья и дома — со средней скоростью, а горы на фоне почти статичны. Вот эта разная скорость перемещения объектов на разной глубине и есть параллакс. 

В вебе параллакс стал моден в 2010-х: обычно для этого брали фоновую картинку и скроллили её медленнее, чем контент на переднем плане. Это чисто визуальный эффект, никакого смысла в нём нет. Сегодня мы сделаем то же самое, причём двумя способами.

Простой способ — параллакс в шапке сайта

Самый простой способ что-то добавить на страницу — использовать готовое решение. В нашем случае мы будем использовать простой скрипт parallax.js — автор выложил исходный код на Гитхаб и объяснил, как им пользоваться. 

Скачиваем оптимизированную минимальную версию parallax.min.js и подключаем через тег script:

<script src="parallax.min.js"></script>

Ещё нам понадобится jQuery — без него скрипт работать не будет. Также мы скачали картинку с сервиса Unsplash, чтобы использовать её для фона.

Чтобы добавить эффект на сайт, нам теперь достаточно пометить блок с картинкой, которая останется на месте. Для этого картинке добавляем свойство data-parallax=»scroll», а остальное сделает подключённый скрипт. Чтобы было что прокручивать ниже, добавим на страницу текст из статьи про то, как работает алгоритм автомобильного навигатора.

Читайте комментарии в коде и смотрите результат на нашем тестовом сервере:

Модный веб: добавляем эффект параллакса на веб-страницу

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>Параллакс</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <!-- подключаем файл со стилями -->
        <link rel="stylesheet" type="text/css" href="style.css" />   
        <!-- подключаем jQuery -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <!-- и скачанный скрипт -->
        <script src="parallax.min.js"></script>
    </head>
<body>
    <!-- формируем шапку сайта и сразу указываем параметр для параллакса -->
    <header class="head"  data-parallax="scroll" data-image-src="header.jpg">
        <h1>КОД</h1>
        <h2>Журнал Яндекс Практикума</h2>
    </header>
    <!-- блок с основным контентом страницы -->
    <div class="content">
        <h2>Что ещё учитывает навигатор </h2>
        <p>Чтобы алгоритм оставался простым и работал только со временем, все остальные параметры дорог тоже привязывают ко времени. Покажем, как это работает, на паре примеров.</p>
        <p><strong>Комфорт</strong>. Если нам нужно построить не самый быстрый, а самый комфортный маршрут, то мы можем отдать предпочтение автомагистралям и дорогам с несколькими полосами — на них обычно и асфальт получше, и резких поворотов поменьше. Чтобы навигатор выбирал именно такие дороги, им можно присвоить коэффициент 0,8 — это виртуально сократит время на дорогу по ним на 20%, а навигатор всегда выберет то, что быстрее.</p>
        <p>С просёлочными и грунтовыми дорогами ситуация обратная. Они редко бывают комфортными, а значит, им можно дать коэффициент 1,3, чтобы они казались алгоритму более долгими и он старался их избегать. А лесным дорогам можно поставить коэффициент 5 — навигатор их выберет, только если это единственная дорога то точки назначения.</p>
        <p><strong>Сложность маршрута и реальное время</strong>. Маршрут из А в Б почти никогда не бывает прямым — на нём всегда есть повороты, развороты и съезды, которые отнимают время. Чтобы навигатор это учитывал, в графы добавляют время прохождения поворота — либо коэффициентом, либо отдельным параметром. Из-за этого алгоритм будет искать действительно быстрый маршрут с учётом геометрии дорог.</p>
        <p><strong>Пробки</strong>. Если есть интернет, то всё просто: навигатор получает данные о состоянии дорог и добавляет разные коэффициенты в зависимости от загруженности. Иногда навигатор ведёт дворами, когда трасса свободна — это не ошибка навигатора, а его прогноз на время поездки: если через 10 минут в этом месте обычно собираются пробки, то там лучше не ехать, а заранее поехать в объезд.</p>
        <p>Если интернета нет, то алгоритм просто использует усреднённую модель пробок на этом участке. Эта модель скачивается заранее и постоянно обновляется в фоновом режиме.</p>
    </div>
</body>
</html>
/* настройки шапки страницы */
.head{
    /* высота картинки с параллаксом */
    min-height: 420px;
}

/* Настройки заголовков в шапке */
    /* заголовок первого уровня */
    .head h1{
        /* размер шрифта */
        font-size: 80px;
        /* выравнивание по центру */
        text-align: center;
        /* тень текста */
        text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.7);
        /* отступ сверху */
        padding-top:50px;
        /* цвет */
        color: yellow;
    }

    /* заголовок второго уровня */
    .head h2{
        font-size: 44px;
        color: yellow;
        text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.7);
        text-align: center;
    }

/* настройки блока с основным содержимым */
.content{
    /* максимальная ширина */
    max-width: 920px;
    /* отступы по краям блока */
    padding: 20px;
    margin: 0 auto;
}

/* настройки абзаца внутри блока с содержимым */
p{
    /* размер шрифта */
    font-size: 24px;
}

Варварский способ — настройка стилей вручную

CSS поддерживает ещё один способ создать такой эффект — зафиксировать изображение и не дать его скроллить. Для этого есть свойство background-attachment:fixed —  то есть фоновая картинка намертво вклеивается в свои координаты и никуда не двигается ни при каком скролле. 

Общая идея такая:

  • Добавляем два блока — один будет с зафиксированной картинкой, второй с текстом. Но пока что не кладём картинку внутрь первого блока, он должен быть пустым.
  • Блоку для картинки присваиваем отдельный класс CSS. Блок всё ещё пустой.
  • В присвоенный класс добавляем свойство background-image, в которое прописываем путь до нужной нам картинки.
  • С помощью магии CSS делаем так, чтобы блок занимал какую-то высоту и ширину, чтобы сквозь него просвечивала нужная картинка.
  • Запрещаем картинке двигаться с места и подгоняем её масштаб под размер блока.
  • Для текстового блока указываем, что его высота должна равняться высоте блока.

В итоге у нас получится два новых стиля:

/* настройки второго параллакса */
.parallax-img {
    /* фоновая картинка */
    background-image: url("map.png");

    /* высота прокрутки картинки */
    min-height: 500px; 

    /* привязываем фоновую картинку, чтобы она не двигалась */
    background-attachment: fixed;
    /* размещаем её по центру */
    background-position: center;
    /* выключаем повторения картинки */
    background-repeat: no-repeat;
    /* подгоняем масштаб картинки под размер блока, в котором она лежит */
    background-size: cover;
}

.parallax-text {
    /* ограничиваем высоту текста размером блока, в котором он лежит */
    height:block;
}

Добавим на ту же страницу в блок «content» новый раздел и карту с автомобильным маршрутом из статьи:

<h2>Как построить маршрут по всей России</h2>
<p>Если нам нужно построить маршрут из Брянска в Тулу, то с точки зрения компьютера это безумно сложная задача: ему нужно перебрать десятки тысяч улиц и миллионы перекрёстков, чтобы понять, какой путь выбрать. С этим плохо справляется даже обычный компьютер, не говоря уже о телефоне.</p>
<p>Если мы в Яндекс Картах построим такой маршрут, то навигатор нам предложит сразу 4 варианта:</p>


<div class="parallax-img"></div>

<div class = "parallax-text" >
     <p>Но мы не ждали полчаса, пока сервер на той стороне посчитает все перекрёстки, а получили результат через пару секунд. Хитрость в том, что алгоритм использует уже заранее просчитанные варианты маршрутов и подставляет их для ускорения.</p>
    <p>Например, если мы поедем в Тулу не из Брянска, а из Синезёрок, то поменяется только начальный маршрут по трассе М3, а всё остальное останется прежним.</p>
    <p>Получается, что навигатору не нужно всё пересчитывать — он находит только ключевые точки пути, а маршрут между ними уже просчитан до этого. Этот приём работает и при перестроении маршрута во время движения: навигатор смотрит, как нужно поменять путь, чтобы вернуть вас на уже известную дорогу</p>
</div>

Модный веб: добавляем эффект параллакса на веб-страницу

Видно, что всё работает, но карта видна не полностью. Это особенность работы с параллаксом — в погоне за красотой мы пожертвовали информативностью. По этой причине картинки для параллакса специально выбирают такие, чтобы если что обрезалось — то и ничего страшного.

Посмотреть работу второго параллакса на странице проекта.

Вёрстка:

Кирилл Климентьев

Simple Parallax — это крошечная и очень простая JS библиотека,
которая позволяет сделать параллакс эффект на любых изображения.

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

Как создать параллакс эффект на сайте?
Библиотека simple Parallax

Вы также можете применить параллакс к тегам picture и srcset.
Реализовать эффект просто, а анимация получается плавная и естественная.

Установка

Установить библиотеку просто, достаточно скачать simple Parallax и добавить скрипт в свой html:


HTML
<script src="simpleParallax.js"></script>
<!--либо CDN-->
<script src="https://cdn.jsdelivr.net/npm/simple-parallax-js@5.0.2/dist/simpleParallax.min.js"></script>

Или можно установить библиотеку через пакетный менеджер npm/yarn:


#npm
npm install simple-parallax-js

#yarn
yarn add simple-parallax-js

После установки с помощью пакетного менеджера вы можете импортировать ее следующим образом:


import simpleParallax from 'simple-parallax-js';

Инициализация

Вы можете использовать любые изображения, чтобы добавить на них js параллакс. Например:


HTML
<img class="thumbnail" src="image.jpg" alt="моя картинка">

Просто добавьте следующий JavaScript код:


JS
var image = document.getElementsByClassName('thumbnail');
new simpleParallax(image);

Пример параллакс эффекта css + js

simpleParallax — по умолчанию

Параллакс возможно применить сразу на нескольких изображениях:


JS
var images = document.querySelectorAll(img);
new simpleParallax(images);

Основы

Если вы не зададите никаких параметров, по умолчанию simpleParallax будет
использовать направление вверх. Это приведет к смещению изображения снизу вверх
при прокрутке вниз, и сверху вниз при прокрутке вверх.

Можно выбрать следующие направления:

  • up
  • right
  • down
  • left
  • up left
  • up right
  • down left
  • down right

Чтобы применить разные настройки к разным изображениям, можно инициализировать несколько
экземпляров
simpleParallax, это не скажется на производительности.


HTML
<img class="left" src="image.jpg" alt="первая картинка">
<img class="right" src="image.jpg" alt="вторая картинка">

JS
var imageLeft = document.querySelector('.left'),
  imageRight = document.querySelector('.right');

new simpleParallax(imageLeft, {
  orientation: 'left'
});
new simpleParallax(imageRight, {
  orientation: 'right'
});

Пример как сделать параллакс

simpleParallax — orientation: ‘left’

Как создать параллакс?

simpleParallax — orientation: ‘right’

Дополнительные настройки

JS параллакс создается с помощью scale — масштабирования, применяемого
к изображению. Scale можно легко изменить (значение по умолчанию-1.3). Чем выше будет
значение scale, тем быстрее и заметнее будет эффект параллакса.


JS
new simpleParallax(image, {
  scale: 1.8
});

Параллакс js

simpleParallax — scale: 1.8

Overflow — еще одна интересная настройка. По умолчания overflow имеет значение flase.
Если установлено значение true, изображение будет вырвано из потока.


JS
new simpleParallax(image, {
  overflow: true
});

js библиотека simple Parallax

simpleParallax — overflow: true, orientation: ‘left’

Если установить параметр delay, то есть задержку. Когда
пользователь прекратит прокрутку, изображение ненадолго продолжит движение.
Это дает очень хороший эффект

В связке с delay работает настройка transition. Она добавит любой CSS эффект к настройке delay


JS
new simpleParallax(image, {
  delay: .6,
  transition: 'cubic-bezier(0,0,0,1)'
});

Простой пример параллакс эффекта на сайте

simpleParallax — delay и transition

Надеюсь, что этот туториал был вам полезен. А что, если вы хотите сделать параллакс из нескольких слоев? Тогда вам стоит посмотреть нашу статью про классный параллакс скроллинг для сайта.

Вводная: про параллакс написано много статей, а сам эффект уже лет 5 как не тренд дизайна. Если вы читаете эту статью, значит вы примерно понимаете что это такое и просто не реализовывали такую красоту раньше)

Простым языком,

параллакс (parallax)

— эффект, при котором скорость движения объектов на переднем и заднем фоне различается.

Наша задача: максимально быстро сотворить что-то вроде этого:

Но не будем тратить время, начнем.

Шаг 1 — Рисуем объекты

Создадим 4 дива и зададим каждому свой класс:

<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
<div class="c4"></div>

Для каждого класса задаем position: fixed, начальное положение (left, top) и размер (width, height). Подбирайте на глаз, как вам больше нравится. Чуть ниже я выложу свой вариант. Не забываем про z-index, чтоб наши блоки не перекрывали основной контент страницы. 

Теперь самое интересное: форма. Я реализовывал летающие объекты блоками с бордер-радиусами. Кто не в теме: с помощью CSS можно задать баббл практически любой формы одним простым параметром: border-radius.

Свойство поддерживает от 1 до 4 наборов значений и разделение слешем.

border-radius: 5%; — задает скругление для всех 4 углов.
border-radius: 5% 6%; — задает скругление 5% для левого верхнего и правого нижнего угла, и 6% — для двух других.
border-radius: 5% 6% 7%; — 5% — для левого верхнего, 6% — для правого верхнего и левого нижнего, 7% — для правого нижнего
border-radius: 5% 6% 7% 8%; — поочередно для левого верхнего, правого верхнего, правого нижнего и левого нижнего.

Самое инересное кроется в разделении слешем. Оно позволяет задать эллиптические углы. Вот вам картинка с htmlbook, которая демонстрирует разницу:
разница между скруглениями

Но если вы думаете, что я предложу вам рисовать блоки вручную, то вы сильно ошибаетесь. Нам ведь нужно уложиться в 5 минут!)

Переходим сюда: https://9elements.github.io/fancy-border-radius/, рисуем блок нужно формы и копируем полученный набор параметров в border-radius, -webkit-border-radius и -moz-border-radius. Поддержку старых браузеров не забываем:)

Чтоб было по красоте, цвет зададим градиентами:

background: linear-gradient(130deg, #974382, #c24fa4); 

Первый параметр — угол, два других — конечные цвета градиента. Покрутите угол, чтоб блоки не казались одинаковыми.

Давайте договоримся, что первые два блока будут на заднем фоне, два последние на переднем. В чем разница?

По правилам перспективы, оптики и скандинавской мифологии:

  • Предметы на переднем плане движутся быстрее, чем на заднем.
  • Предметы вне фокуса (ближе или дальше) размываются.

Итак, первым двум дивам зададим filter: blur(5px), а двум другим — filter: blur(3px). При желании можно задать небольшую прозрачность (opacity: 0.7;). Про скорость поговорим чуть позже, когда займемся анимацией.

Итак, у вас должно получится что-то вроде этого:

результат баббл на css произвольной формы
Все стили в одном месте:

.c1 {
position: fixed;
right: 160px;
top: 676px;
z-index: -100;
width: 100px;
height: 100px;
background: linear-gradient(#6A2A88, #2d1871);
filter: blur(5px);
opacity: 0.7;
-webkit-border-radius: 21% 79% 57% 43% / 23% 41% 59% 77% ;
-moz-border-radius: 21% 79% 57% 43% / 23% 41% 59% 77% ;
border-radius: 21% 79% 57% 43% / 23% 41% 59% 77% ; }
.c2 {
position: fixed;
left: 99px;
top: 940px;
z-index: -100;
width: 200px;
height: 200px;
background: linear-gradient(100deg,#843984, #4d247f);
filter: blur(5px);
opacity: 0.7;
-webkit-border-radius: 51% 49% 36% 64% / 57% 62% 38% 43%;
-moz-border-radius: 51% 49% 36% 64% / 57% 62% 38% 43%;
border-radius: 51% 49% 36% 64% / 57% 62% 38% 43%;
}
.c3 {
position: fixed;
left: 1602px;
top: -150px;
z-index: -100;
width: 100px;
height: 100px;

background: linear-gradient(90deg, #883c84, #532480);
filter: blur(1px);
-webkit-border-radius: 40% 60% 61% 39% / 56% 37% 63% 44%;
-moz-border-radius: 40% 60% 61% 39% / 56% 37% 63% 44%;
border-radius: 40% 60% 61% 39% / 56% 37% 63% 44%;
}
.c4 {
position: fixed;
left: 212px;
top: 480px;
z-index: -100;
width: 100px;
height: 100px;

background: linear-gradient(130deg, #974382, #c24fa4);
filter: blur(1px);

-webkit-border-radius: 49% 51% 57% 43% / 44% 46% 54% 56% ;
-moz-border-radius: 49% 51% 57% 43% / 44% 46% 54% 56% ;
border-radius: 49% 51% 57% 43% / 44% 46% 54% 56% ;
}

Код скомпонован для удобства восприятия, ни кто вам не мешает выделить общие стили в отдельный класс и убрать лишние переносы строк.

Пришло время заняться анимацией.

Шаг 2 — Параллакс эффект

Раз уж статья называется «parallax за 5 минут», не будем сильно мудрить и воспользуемся готовым решением.

Я буду использовать библиотеку rellax.js (

сайт

|

github

), ну и jQuery, куда без него.

Скачайте библиотеки и подключите в файле проекта. Если ты молодец и используешь npm, воспользуйся командами:

 npm install jquery --save
npm install rellax --save

Основная причина, по которой я использую rellax.js — простота. Для того, чтоб добавить эффектную анимацию достаточно написать пару строк:

$(document).ready(function(){
var c1 = new Rellax('.c1', {
speed: 5
});
var c2 = new Rellax('.c2', {
speed: 8
});
var c3 = new Rellax('.c3', {
speed: -4
});
var c4 = new Rellax('.c4', {
speed: -7
});
});

Второй параметр принимает набор характеристик. Самый востребованный — скорость. Вспомним о чем мы говорили: задний фон движется медленнее. Отрицательное значение позволит задать скорость ниже, чем скорость прокрутки страницы. Положительное — быстрее скорости прокрутки.

Готово! Сверяемся с секундомером.

Напоследок пара советов:

  • Не забывайте про адаптивность. Тестируйте анимацию при разных разрешениях экрана. В мобильной версии этот эффект вообще лучше отключить. Иначе основной контент страницы будет перекрываться.
  • Четко определите для себя «слои», на которых будут располагаться элементы. Скорость и размытие элементов на слое должны совпадать или отличаться незначительно.
  • Экспериментируйте с перекрытиями элементов: пусть элементы на переднем фоне накладываются на фоновые, «обгоняют» их. Это добавит глубину.
  • Не используйте много элементов, это рассеивает внимание.
  • Ознакомьтесь с документацией parallax.js на гитхабе.

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

Создание контентного сайта на Jekyll от А до Я

Материалы урока и готовый результат: Скачать

Рекомендуемые уроки и инструменты

  • Настройка VS Code для верстки: Ознакомиться с уроком
  • Cubic-Bezier CSS Generator: Перейти на сайт
  • Пипетка Instant Eyedropper: Скачать
  • Урок по EMMET (быстрая верстка): Смотреть на YouTube
  • Справочник EMMET (сокращения): Ознакомиться с уроком

Cubic-Bezier анимация для скролла:

Ниже представлен скриншот из сервиса Cubic-Bezier с изображением позиционирования точек Animation/Time. Изменяя положение ползунков на сайте сервиса, вы можете настроить анимации по своему вкусу.

--transition: transform .75s cubic-bezier(.075, .5, 0, 1);

CSS анимация Cubic-Bezier

Обновленный метод определения CSS переменной из JavaScript

Чтобы не заставлять браузер ежесекундно проверять cssText и снизить нагрузку, мы можем задать конкретное CSS свойство с переменной и сделать это не для «body», а непосредственно для «documentElement», то-есть для «html» (в CSS это :root). setProperty устанавливает и изменяет конкретное CSS свойство, поэтому в нашем случае, сложение с присваиванием +=, которое влечет за собой дополнительную проверку уже имеющегося набора свойств, использовать не обязательно.

	document.documentElement.style.setProperty('--scrollTop', `${this.scrollY}px`)

Премиум уроки от WebDesign Master

Другие уроки по теме «Верстка»

  • Создание сайта с крутой анимацией скролла (GSAP) | Материалы урока
  • Создание красивого сайта с горизонтальным Parallax эффектом | Материалы урока
  • Создание сайта портфолио с крутой анимацией | Материалы урока
  • Создание Parallax эффекта на сайте при движении мыши | Материалы урока
  • Создание красивого сайта с поддержкой темной темы (HTML, CSS, GSAP) | Материалы урока

Понравилась статья? Поделить с друзьями:
  • Как написать папе письмо на день рождения
  • Как написать папе на день рождения подарок
  • Как написать папа я тебя очень сильно люблю
  • Как написать папа мой любимый
  • Как написать панчлайн