Создание анимированного липкого заголовка с произвольным смещением

Липкие элементы используются во всем Интернете. С появлением 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 позволяет нам создавать лучший опыт для конечного пользователя более легко и естественно. И поддержка с каждым днем ​​все лучше и лучше. 🏆

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *