Статьи

Создайте анимированное липкое навигационное меню с Vanilla JavaScript

При добавлении меню навигации на веб-страницу необходимо учитывать множество факторов. Например, где его разместить, как его стилизовать, как сделать его отзывчивым. Или, может быть, вы хотите добавить какую-то анимацию (со вкусом, конечно). В этот момент у вас может возникнуть соблазн получить плагин jQuery, который сделает большую часть этого за вас. Но этого не должно быть! На самом деле довольно просто создать собственное решение в несколько строк кода.

В этой статье я покажу, как создать анимированное липкое навигационное меню с ванильным JavaScript, CSS и HTML. Конечный продукт будет скользить вверх, когда вы будете прокручивать страницу вниз, а затем возвращаться обратно в вид (со стильным эффектом прозрачности), когда вы будете прокручивать страницу вверх. Это техника, используемая такими популярными сайтами, как Medium и Hacker Noon .

После прочтения вы сможете использовать эту технику в своих собственных проектах, надеюсь, с большим эффектом. В конце статьи есть демо для нетерпеливых.

Ниже приведен скелет HTML-кода, с которым мы будем работать. Ничего особенного здесь не происходит.

<div class="container">
  <div class="banner-wrapper">
    <div class="banner">
      <div class="top">
        <!-- Navbar top row-->
      </div>
      <div class="nav">
        <!-- Links for navigation-->
      </div>
    </div>
  </div>

  <div class="content">
    <!-- Awesome content here -->
  </div>
</div>

Применяя маленький стиль

Давайте добавим некоторые стили к основным элементам.

Основной контейнер

Нам нужно удалить все присущие стили браузера и установить ширину нашего контейнера на 100%.

 *{
  box-sizing:border-box;
  padding: 0;
  margin: 0;
}

.container{
  width: 100%;
}

Баннер Контейнер

Это обертка вокруг меню навигации. Он всегда липкий и скользит, чтобы скрыть или открыть меню навигации при вертикальной прокрутке страницы. Мы даем ему значение z-index

 .banner-wrapper {
  z-index: 4;
  transition: all 300ms ease-in-out;
  position: fixed;
  width: 100%;
}

Баннерная секция

Это содержит меню навигации. Изменения в положении и цвете фона анимируются с помощью свойства transition

 .banner {
  height: 77px;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  background: rgba(162, 197, 35, 1);
  transition: all 300ms ease-in-out;
}

Раздел контента

Этот раздел будет содержать фоновое изображение и текст. Мы добавим эффект параллакса к этой части страницы в следующем разделе статьи.

 .content {
  background: url(https://unsplash.it/1400/1400?image=699) center no-repeat;
  background-size: cover;
  padding-top: 100%;
}

Анимация меню

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

 (() => {
  'use strict';

  const handler = () => {
    //DOM manipulation code here
  };

  window.addEventListener('scroll', handler, false);
})();

Установка некоторых начальных значений

Мы будем использовать переменную refOffset Это инициализируется до 0 Мы будем использовать переменную bannerHeight.banner-wrapper.banner

 let refOffset = 0;
let visible = true;
const bannerHeight = 77;

const bannerWrapper = document.querySelector('.banner-wrapper');
const banner = document.querySelector('.banner');

Установление направления прокрутки

Далее нам нужно установить направление прокрутки, чтобы мы могли соответственно отобразить или скрыть меню.

Мы начнем с переменной с именем newOffset При загрузке страницы это будет установлено в значение window.scrollY — количество пикселей, которые документ в настоящий момент прокручивает по вертикали (поэтому 0 Когда пользователь прокручивает, newOffset Если оно больше значения, хранящегося в bannerHeight

 const newOffset = window.scrollY;

if (newOffset > bannerHeight) {
  // Menu out of view
} else {
  // Menu in view
}

Прокрутка вниз сделает newOffsetrefOffset Прокрутка вверх сделает newOffsetrefOffset После выполнения этого сравнения нам потребуется обновить refOffsetnewOffset

 if (newOffset > bannerHeight) {
  // Menu out of view
  if(newOffset > refOffset) {
    // Hide the menu
  } else if (newOffset < refOffset) {
    // Slide menu back down
  }

  refOffset = newOffset;
} else {
  // Menu in view
}

Анимация меню

Наконец, давайте добавим анимацию, чтобы показать и скрыть меню. Мы можем сделать это, используя следующий CSS:

 .animateIn{
  transform: translateY(0px);
}

.animateOut{
  transform: translateY(-100%);
}

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

 if (newOffset > bannerHeight) {
  if (newOffset > refOffset) {
    bannerWrapper.classList.remove('animateIn');
    bannerWrapper.classList.add('animateOut');
  } else {
    bannerWrapper.classList.remove('animateOut');
    bannerWrapper.classList.add('animateIn');
  }
  banner.style.background = 'rgba(162, 197, 35, 0.6)';
  refOffset = newOffset;
} else {
  banner.style.backgroundColor = 'rgba(162, 197, 35, 1)';
}

Как видите, мы удаляем / применяем различные классы CSS соответственно.

демонстрация

Вот демонстрация рабочего меню.

Вывод

В этой статье описывается, как вы можете создать анимированное навигационное меню в несколько строк кода, используя только простой JavaScript — никакой jQuery не требуется. Меню перемещается, чтобы исчезнуть при прокрутке вниз, и возвращается к виду с эффектом прозрачности при прокрутке вверх. Это делается путем мониторинга вертикального направления прокрутки и применения CSS-преобразований к элементу DOM по мере необходимости. Такое индивидуальное решение дает вам больше свободы для простого и гибкого проектирования в соответствии с вашими требованиями и спецификациями.

Хотите улучшить свои навыки JavaScript? Проверьте наши курсы Введение в JavaScript и
JavaScript: следующие шаги .

Эта статья была рецензирована Vildan Softic . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!