Эффект прокрутки страницы в CSS и JavaScript Содержимое при прокрутке предыдущего элемента в CSS и JavaScript

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



ДЕМО
ИСХОДНИКИ


В этом эффекте используется закрепленное значение свойства CSS position. При использовании липкой позиции мы обычно устанавливаем top для липкого элемента; элемент изначально ведет себя как элемент относительного положения (обычная прокрутка), пока не достигнет указанной верхней позиции и не станет фиксированным.

Для раскрывающего нижнего блока мы хотим создать противоположный эффект: мы хотим, чтобы элемент был зафиксирован в начале, а затем начал прокручиваться (как элемент относительного положения) после того, как его содержимое было обнаружено. Этого можно добиться, установив значение bottom (а не top) в комбинации с фиксированной позицией.

Однако, если мы установим нижнюю границу 0 пикселей, часть содержимого раздела может быть не видна (он ведет себя как фиксированный элемент с нижней границей 0 пикселей). Мы можем перемещать элемент по оси Y, используя отрицательное нижнее значение. Новое нижнее значение будет равно разнице между его высотой и высотой окна.

Эффект прокрутки страницы в CSS и JavaScript

Этот урок - вдохновление от портфолио Клаудио Гульери.


<section class="position-relative zindex-2 bg shadow-sm">
  <!-- section with a normal flow -->
</section>

<section class="revealing-hero bg zindex-1 js-revealing-hero">
  <!-- Revealing Hero content -->
</section>

В CSS нам нужно установить значение позиции:


.revealing-hero {
  position: sticky;
  min-height: 100vh;
}

Мы можем установить нижнее значение в JavaScript:


var revealingHero = document.getElementsByClassName('js-revealing-hero')[0];
revealingHero.style.bottom = (window.innerHeight - revealingHero.offsetHeight)+'px';

Теперь, когда у нас есть поведение при прокрутке, мы можем улучшить эффект, добавив наложение со значением непрозрачности, которое изменяется при прокрутке. Мы будем использовать псевдоэлемент ::after для создания эффекта:


.revealing-hero {
  --reavealing-hero-overlay-opacity: 1; // overlay layer opacity - modified using JS

  &::after { // overlay layer
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    pointer-events: none;
    background-color: var(--color-black);
    opacity: var(--reavealing-hero-overlay-opacity);
  }
}

Непрозрачность элемента ::after устанавливается с помощью настраиваемого свойства CSS --reavealing-hero-overlay-opacity. Это значение можно изменить при прокрутке (от 1 до 0) с помощью API Intersection Observer.

Мы можем создать объект RevealingHero, который мы используем для инициализации эффекта:


var RevealingHero = function(element) {
  this.element = element;
  this.scrollingFn = false;
  this.scrolling = false;
  initRevealingHero(this);
};

function initRevealingHero(element) {
  createTopElement(element); // create a new node - to be inserted before the sticky element
  initRevealingHeroEffect(element); // change the ::after element opacity on scroll
};

Функция createTopElement используется для создания скрытого элемента, который вставляется прямо перед разделом «Revealing Hero section». Наблюдатель пересечения может использоваться для определения, когда этот элемент входит в область просмотра, чтобы обновить значение --reavealing-hero-overlay-opacity:


function initRevealingHeroEffect(element) {
  var observer = new IntersectionObserver(revealingHeroCallback.bind(element));
  observer.observe(element.prevElement);
};

function revealingHeroCallback(entries) {
  if(entries[0].isIntersecting) {
    if(this.scrollingFn) return; // listener for scroll event already added
    this.scrollingFn = revealingHeroScrolling.bind(this);
    window.addEventListener('scroll', this.scrollingFn);
  } else {
    if(!this.scrollingFn) return; // listener for scroll event already removed
    window.removeEventListener('scroll', this.scrollingFn);
    this.scrollingFn = false;
  }
};

function revealingHeroScrolling() {
  if(this.scrolling) return;
  this.scrolling = true;
  window.requestAnimationFrame(animateRevealingHero.bind(this));
};

function animateRevealingHero() {
  // change opacity value
};

Когда element.prevElement находится внутри области просмотра (entry [0] .isIntersecting == true в функции discoveralingHeroCallback), мы прослушиваем событие прокрутки окна и соответственно обновляем значение свойства CSS.


🔖 Выбор по тегам ×

Top