В этом уроке мы покажем, как создать раздел, который показывает свое содержимое при прокрутке предыдущего элемента.
В этом эффекте используется закрепленное значение свойства CSS position
. При использовании липкой позиции мы обычно устанавливаем top
для липкого элемента; элемент изначально ведет себя как элемент относительного положения (обычная прокрутка), пока не достигнет указанной верхней позиции и не станет фиксированным.
Для раскрывающего нижнего блока мы хотим создать противоположный эффект: мы хотим, чтобы элемент был зафиксирован в начале, а затем начал прокручиваться (как элемент относительного положения) после того, как его содержимое было обнаружено. Этого можно добиться, установив значение bottom
(а не top
) в комбинации с фиксированной позицией.
Однако, если мы установим нижнюю границу 0 пикселей, часть содержимого раздела может быть не видна (он ведет себя как фиксированный элемент с нижней границей 0 пикселей). Мы можем перемещать элемент по оси Y, используя отрицательное нижнее значение. Новое нижнее значение будет равно разнице между его высотой и высотой окна.
Этот урок - вдохновление от портфолио Клаудио Гульери.
<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.