Всем привет! Буквально за 5 минут расскажу, как сделать parallax-эффект, который помог нам наглядно показать стилистические различия между светлой и темной темами на сайте «Дизайн-система НЛМК».

Parallax-эффект позволяет пользователю увидеть изменения темы у компонентов при скролле страницы, причем сами компоненты зафиксированы, а линия смены темы двигается синхронно со скроллом.

Но для начала мне следует представиться. Я - frontend-разработчик “НЛМК - Информационные технологии”, занимаюсь созданием различных решений для упрощения работы промышленных цехов. Один из моих проектов - «Дизайн-система НЛМК», которая является основой для других, более сложных решений в других проектах.

Разработка структуры сайта, который является своеобразной "визитной карточкой" «Дизайн-системы», дала простор для интересных фич по его стилизации.

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

Приступим к реализации. Для этого нам потребуются старые-добрые HTML и CSS, а также препроцессор SCSS. Ну и базовое знание БЭМ также не повредит :)

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

<div class="screen">
  <div class="screen__part screen__part--light"></div>
  <div class="screen__part screen__part--dark"></div>
</div>

Класс .screen__part объединяет в себе общие стили дочерних элементов, а модификаторы --light и --dark его расширяют.

Начнем написание стилей блоков. Создадим общий класс блока .screen, который содержит в себе элемент .screen__part:

.screen {
  &__part {
    height: 100vh;
  }
}

Предполагается, что высота каждого элемента с картинками будет равна высоте экрана (оно же 100vh), чтобы пользователь мог рассмотреть все компоненты. Далее добавим свойства модификаторов .screen__part--light и .screen__part--dark:

&--light {
  background: #EDEEF2 url("../images/screen_white.jpg") no-repeat center/cover fixed;
}

&--dark {
  background: #454C5E url("../images/screen_black.jpg") no-repeat center/cover fixed;
  clip-path: polygon(0 0, 100% 12vh, 100% 100%, 0% 100%);
  position: relative;
  top: -12vh;
}

Здесь используются более комплексные стили, поэтому давайте разберемся подробнее. Свойство .background у обоих элементов может заменить десяток аналогичных свойств для стилизации фоновых картинок. Но для наглядности разобьем его на части (возьмем значения из “светлого” блока):

background-color: #EDEEF2;
background-image: url("../images/screen_white.jpg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-attachment: fixed;

Первое и второе свойства вполне понятны - они содержат фоновый цвет и путь к фоновой картинке. Третьим свойством мы размещаем изображение один раз и больше его не повторяем. Свойство background-position указывает начальное положение фона, в нашем случае мы располагаем его по центру как по горизонтали, так и по вертикали. Свойством background-size мы указываем размер фонового изображения, причем значением cover мы сохраняем пропорции изображения так, чтобы его высота равнялась высоте элемента. Свойством background-attachment и значением fixed мы фиксируем фоновое изображение и предотвращаем его перемещение (или фиксируем его “на заднем плане”, кому как удобнее)

Теперь рассмотрим свойство clip-path. С его помощью можно создавать блоки в форме разных геометрических фигур. Если в качестве значения использовать функцию polygon, то можно получить блок в форме четырехугольника. В нашем примере мы передаем в функцию четыре пары значений, четыре пары координат углов четырехугольника (левый верхний, правый верхний, правый нижний, левый нижний):

 polygon(0 0, 100% 12vh, 100% 100%, 0% 100%);

Но если оставить все как есть, то окажется, что то, что было обрезано при помощи clip-path, оставит под собой пустое пространство или “зазор”. Поэтому при помощи свойств position и top мы поднимаем “темный” блок ровно на столько, сколько по высоте было обрезано, а именно на 12vh (главное помнить, что система координат начинается в левом верхнем углу, и поэтому в свойстве надо поставить знак “минус”, иначе “темный” блок окажется еще ниже).

Ниже представлен демо-результат проделанной работы:

На этом, в принципе, все! Используя несколько несложных свойств css, мы реализовали интересный parallax-эффект, который смог в полной мере раскрыть темизацию используемых компонентов.  

Комментарии (9)


  1. ionicman
    10.02.2022 11:32
    +10

    Побуду занудой - но вроде как эффект параллакса - это уменьшение скорости движения объектов в зависимости от их удаления от наблюдателя. И для меня параллакс вот, например.

    А здесь просто перекрытие в зависимости от положения скролла (во всяком случае, именно так себя ведёт себя демка на мобильном FF) , нет?


    1. NikDoomchan Автор
      10.02.2022 12:21

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


      1. fugasio
        10.02.2022 12:53
        +7

        Побуду ещё большим занудой, но Паралла́кс (греч. παράλλαξις, от παραλλαγή, «смена, чередование») — изменение видимого положения объекта относительно удалённого фона в зависимости от положения наблюдателя.


      1. fugasio
        10.02.2022 12:55

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


        1. NikDoomchan Автор
          10.02.2022 20:55

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

          Тем более изначально речь шла про сайт-лендинг, который демонстрирует возможные фичи проекта "Дизайн системы", сами стилизованные компоненты в проект лендинга не входят.


  1. LDZ
    10.02.2022 12:08
    +1

    // не рекомендуется использовать отрицательный margin в реальных проектах

    Почему? Есть обоснования?


    1. Carduelis
      10.02.2022 13:11

      Будет горизонтальный скролл страницы на iOs, если не прикрыть overflow: hidden; , который может обрезать тени, вызвать дополнительные визуальные баги или отсутствие работы backdropFilter.

      А еще проблемы с width: 100%; или необходимость calc()


      1. LDZ
        10.02.2022 13:34
        +1

        Ну так можно сказать почти про любое свойство. Всегда есть несколько НО, которые нужно учитывать. Но это не значит, что их "не рекомендуется использовать в реальных проектах"


    1. NikDoomchan Автор
      10.02.2022 14:18

      Конкретно в данном случае отрицательный margin повлечет смещение всех элементов, идущих после элемента с отрицательным margin.
      Ниже предложена альтернатива - position: relative и отрицательный top.