Эффект параллакса при прокрутке страницы

Интересный параллакс-эффект c помощью jQuery

Посмотрите пример на Codepen

Создадим базовую разметку и добавим стили

Для начала создаем разметку

HTML

<div class="parallax">
  <div class="parallax__flex">
    <div class="parallax__image"><img src="https://picsum.photos/1920/1081" alt=""/></div>
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
    <div class="parallax__image"><img src="https://picsum.photos/1920/1082" alt=""/></div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__image"><img src="https://picsum.photos/1920/1083" alt=""/></div>
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
    <div class="parallax__image"><img src="https://picsum.photos/1920/1084" alt=""/></div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__image"><img src="https://picsum.photos/1920/1085" alt=""/></div>
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
    <div class="parallax__image"><img src="https://picsum.photos/1920/1086" alt=""/></div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__image"><img src="https://picsum.photos/1920/1087" alt=""/></div>
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
    <div class="parallax__image"><img src="https://picsum.photos/1920/1088" alt=""/></div>
  </div>
  <div class="parallax__flex">
    <div class="parallax__image"><img src="https://picsum.photos/1920/1089" alt=""/></div>
    <div class="parallax__body">
      <div class="parallax__title">Lorem ipsum</div>
      <div class="parallax__text">Dolor sit amet, consectetur adipisicing elit. Soluta modi, distinctio quae magni molestias odit cum veritatis ipsam quas vero eveniet cupiditate fugiat animi, saepe tempora eaque delectus officia suscipit?</div>
    </div>
  </div>
</div>


Назначаем стили для блоков

CSS

.parallax__flex {
  display: flex;
}
.parallax__image {
  width: 60%;
  overflow: hidden;
}
.parallax__image img {
  -o-object-fit: cover;
  object-fit: cover;
  width: 100%;
  height: 100%;
  display: block;
}
.parallax__body {
  width: 40%;
  padding: 60px;
  background: #fff;
}
.parallax__title {
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 30px;
}
.parallax__text {
  font-size: 18px;
}
@media (max-width: 991.98px) {
  .parallax__flex {
    flex-direction: column;
  }
  .parallax__image {
    width: 100%;
  }
  .parallax__body {
    width: 100%;
  }
}

Про object-fit подробнее - Zoom-эффект: масштаб и позиционирование изображения



Скачиваем и подключаем jQuery

Для этого этого примера будем использовать библиотеку jQuery

Скачаем библиотеку на официальном сайте jQuery

Нажимаем кнопку Download

1

Ищем ссылку на минифицированную версию jQuery и нажимаем

2

Сохраняем файл в папку с другими js-файлами

3

Подключаем файл jquery-3.5.1.min.js перед закрывающим тегом </body> до основного js-файла

3



Пишем jQuery код

Основной main.js файл будет содержать следующий код

$(window).on('load', function(){ /* внутренние функции сработают когда будут загружены все изображения */

  function parallax(){
    $('.parallax__image').each(function(){ /* внутри каждого блока с классом .parallax__image */
      const img = $(this).find('img') /* находим изображение по тегу img */
      const windowTop = $(window).scrollTop() /* вычисляем сколько уже прокручего от верха страницы */
      const windowHeight = $(window).height() /* вычисляем высоту окна браузера */
      const windowBottom = $(window).scrollTop() + windowHeight /* вычисляем где низ окна браузера */
      const imageTop = $(this).offset().top /* вычисляем расстояние от верха страницы до верха блока с изображением  */
      const imageHeight = $(this).height() /* вычисляем высоту блока с изображением */
      const imageBottom = $(this).offset().top + imageHeight /* вычисляем низ блока с изображением */

      if (!(imageTop > windowBottom || imageBottom < windowTop)) { /* проверяем находится ли блок с изображением в видимой области окна браузера */
        const sub = imageTop - windowTop /* вычисляем разницу верха блока с изображением и верха окна браузера */
        if (sub >= 0) { /* если верх изображения ниже верха окна браузера */
          img.css({ /* назначаем изображению динамические inline-свойства */
            transform: `scaleX(${(sub / 2000) + 1})` /* изображение будет сужаться (scaleX) при прокрутке взависимости от sub */
          })
        } else { /* иначе если верх изображения выше верха окна браузера */
          img.css({
            transform: `scaleX(1) translateY(${(-sub / 2)}px)` /* scaleX сбрасываем до значения 1 и перемещаем изображение вниз взависимости от sub */
          })
        }
      }
    })
  }
  parallax() /* запускаем функцию при загрузке страницы */
  $(window).scroll(function(){
    parallax() /* запускаем функцию при прокрутке страницы */
  })
  $(window).resize(function(){
    parallax() /* запускаем функцию при изменинии размеров окна браузера */
  })
})

Выше в коде написал комментарии, чтобы понимать какая строка за что отвечает, но хотел бы уточнить еще некоторые моменты

  1. Используем $(window).on('load', function(){}), чтобы изображения успели загрузиться и только потом сработала функция parallax(). Если бы использовали $(document).ready(function(){}), то функции внутри запускались бы сразу после загрузки DOM, и так как изображения не успели бы еще загрузиться, мы бы не смогли получить корректные данные о высоте и положении элементов, и функция parallax() работала бы некорректно

  2. scaleX(${(sub / 2000) + 1}) - опытным путем определяем на какое число делить разницу sub, получаем значение приближенное к 0, а так как scaleX() принимает значение приближенные к 1, то прибавляем единицу, чтобы изначально получить значение немного больше единицы и растянуть изображение. Аналогично и с translateY(${(-sub / 2)}px), только здесь необходимо получить значения примерно от 0 до нескольких сотен пикселей

  3. Функцию parallax() запускаем несколько раз, так как данные о размерах и положении элементов необходимо получать и при загрузке страницы и при прокрутке страницы и при изменении размеров окна браузера



Таким образом можно применять и другие эффекты для элементов при прокрутке страницы

Посмотрите код на Codepen, попробуйте изменить некоторые значения, чтобы подробнее разобраться, как работает данный эффект



Изображения - https://picsum.photos/