Создание анимированного липкого заголовка с произвольным смещением
Липкие элементы используются во всем Интернете. С появлением position: sticky
свойство, мы могли бы создавать липкие элементы без плагинов JavaScript. Но создание липких элементов с анимацией невозможно без использования JavaScript.
Технические характеристики
Задача состоит в том, чтобы создать липкий заголовок, который появляется, когда пользователь прокручивает статический заголовок или находится в пользовательской позиции смещения. При прокрутке вниз статический заголовок должен оставаться на своем месте, а липкий заголовок должен скатываться вниз. При прокрутке вверх липкий заголовок должен исчезнуть, а статичный заголовок должен скатиться вниз. Обратите внимание, что содержимое статического заголовка и закрепленного заголовка различается.
Решение
Чтобы упростить понимание спецификаций, см. эту ручку, содержащую полное решение:
Разбивка
Чтобы лучше понять, как работает этот код, мы должны изучить структуру HTML.
HTML
Вот упрощенный предварительный просмотр структуры HTML:
<main>
<header>
<div class="header header--alpha">
...
</div>
<div class="header header--beta">
...
</div>
</header>
<div class="fake-header"></div>
<article>
...
</article>
</main>
Внутри main
элемент, у нас есть header,
.fake-header
а также article
элементы. Делать position: sticky
работа, липкий элемент должен быть внутри прокручиваемого элемента — main
элемент в нашем случае.
Заголовок содержит два элемента:
.header--alpha
статический заголовок и.header--beta
липкий заголовок.
CSS
Во-первых, давайте стилизуем наш элемент-обертку. По умолчанию он должен иметь относительную позицию и прилипать после достижения смещения.
header {
top: 0;
position: relative;
overflow: hidden;
}
header.sticky {
position: sticky;
}
Недвижимость top: 0
удостоверился бы, что наш заголовок застрял наверху, а свойство overflow: hidden
скрывает все, что находится за пределами header
элемент.
Далее мы должны определить поведение частей заголовка.
.header--alpha {
transition: .225s ease-out;
}
.sticky .header--alpha {
opacity: .5;
transform: translateY(-100%);
transition: none;
}
.header--alpha
, наш статический заголовок виден по умолчанию. Когда пользователь прокручивает смещение, и обертка header
элемент становится липким, он будет мгновенно переведен за пределы элемента-обертки без какого-либо эффекта перехода. Обратите внимание, что элемент будет перемещен, когда он перейдет в исходное положение, когда эффект прилипания не будет активен.
.header--beta {
position: absolute;
top: 0;
left: 0;
right: 0;
opacity: .5;
transform: translateY(-100%);
}
.sticky .header--beta {
opacity: 1;
transform: translateY(0);
transition: .35s ease-out;
}
.header--beta
наш липкий заголовок позиционируется абсолютно и транслируется вне обертки header
элемент. Когда липкий эффект активирован, он будет переведен и перемещен в исходное положение.
JavaScript
Возможно, вы заметили .fake-header
элемент.
.fake-header {
height: 1px;
position: relative;
}
Этот элемент служит смещением для прокрутки. Когда он достигает верхней части области просмотра, заголовок становится липким. И когда заголовок станет липким, поддельный элемент будет выдвинут вверх на высоту заголовка плюс один дополнительный пиксель. Когда пользователь прокручивает вверх и достигает поддельного элемента в новой позиции, эффект прилипания отключается.
const $realSticky = document.querySelector("header");
const $fakeSticky = document.querySelector(".fake-header");
const stickyHeader = () => function() {
const sr1 = $fakeSticky.getBoundingClientRect();
const sr2 = $realSticky.getBoundingClientRect();
if (sr1.top > 0) {
$realSticky.classList.remove("sticky");
$fakeSticky.style.top = 0;
} else {
$realSticky.classList.add("sticky");
$fakeSticky.style.top = `-${sr2.height + 1}px`;
}
};
window.addEventListener("scroll", _.debounce(stickyHeader(), 15));
В этом примере Лодаш функция используется для выполнения задачи в событии прокрутки.
Я знаю, что мог бы написать лучший код JS и не добавлять .fake-header
element, но я хотел создать демонстрацию без лишних вычислений.
Поскольку статический заголовок определяет высоту элемента-обертки, у нас возникает проблема с выбором или щелчком по содержимому сразу после прикрепленного заголовка, как только он появится.
Мы могли бы использовать события-указатели, чтобы решить эту проблему:
header {
pointer-events: none;
}
.header {
pointer-events: all;
}
Сначала мы бы установили pointer-events
к none
к header
элемент, чтобы отключить события щелчка/наведения, а затем мы бы установили pointer-events
к all
чтобы снова включить их.
Вывод
Вы можете увидеть полную демонстрацию на моем кодепене.
В этой демонстрации используется position: sticky
а также pointer-events
свойства, которые имеют ограниченную поддержку.
Я очень рад видеть, как быстро движется CSS. Совершенно новые свойства, такие как position: sticky
а также pointer-events
позволяет нам создавать лучший опыт для конечного пользователя более легко и естественно. И поддержка с каждым днем все лучше и лучше. 🏆