Как скрыть/показать панель уведомлений при прокрутке

От автора: в предыдущем уроке мы узнали, как скрыть и показать липкий заголовок при прокрутке. Сегодня давайте создадим нечто подобное: липкий заголовок, верхняя часть которого (заголовок панели уведомлений) исчезнет при прокрутке вниз и появится при прокрутке вверх.

Что мы создаем?

Ссылка на предыдущий урок. Вот что мы собираемся создать в этом уроке (прокрутите, чтобы проверить поведение):

Начните с разметки страницы

Заголовок будет состоять из двух частей: верхней и нижней.

В верхней части будет специальное уведомление о бесплатной доставке и контактная информация.

Нижняя часть будет содержать логотип компании и меню. По умолчанию меню не появляется.

Как скрыть/показать панель уведомлений при прокрутке

Эта структура заголовка распространена, особенно в магазинах электронной коммерции. Заголовок/панель уведомлений используется для уведомления пользователей о специальных скидках, акциях, информации о доставке и других вещах. Они играют очень важную роль, поскольку являются первым, что видит посетитель на сайте. Умная панель уведомлений может привлечь больше покупателей и повысить продажи.

Как скрыть/показать панель уведомлений при прокрутке

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

<header class="page-header"> <nav> <div class="header-top"> <div class="container"> <div class="d-flex flex-column flex-row@s justify-content-between text-center"> <div>...</div> <div>...</div> </div> </div> </div><!-- /header-top --> <div class="header-bottom"> <div class="container"> <div class="d-flex justify-content-between"> <a href=""> <img width="178" height="38" src="horizontal-logo-mobile.svg" alt="forecastr logo"> </a> <div class="d-flex"> <ul class="menu d-flex flex-column flex-row@m align-items-center justify-content-between">...</ul> <button aria-label="Toggle menu" class="toggle-menu"> <svg aria-hidden="true" width="30" height="30" viewBox="0 0 24 24"> <path d="M4 22h-4v-4h4v4zm0-12h-4v4h4v-4zm0-8h-4v4h4v-4zm3 0v4h17v-4h-17zm0 12h17v-4h-17v4zm0 8h17v-4h-17v4z" /> </svg> </button> </div> </div> </div> </div><!-- /header-bottom --> </nav>
</header> <!-- sections here -->

Определим несколько вспомогательных классов

Для простоты мы обсудим только стили, относящиеся к заголовку. Вы можете изучить все стили проекта, кликнув вкладку CSS демонстрационного проекта.

Чтобы стилизовать заголовок, нам понадобятся несколько вспомогательных классов. Вместо того, чтобы включать фреймворк CSS, такой как Tailwind, давайте сами определим эти классы:

.container { padding: 0 15px; max-width: 100%;
} .d-flex { display: flex;
} .flex-column { flex-direction: column;
} .align-items-center { align-items: center;
} .justify-content-between { justify-content: space-between;
} .text-center { text-align: center;
} @media (min-width: 600px) { .container { padding: 0 30px; } .flex-row\@s { flex-direction: row; }
} @media (min-width: 900px) { .flex-row\@m { flex-direction: row; }
}

Укажем стили заголовков

На маленьких экранах (<600 пикселей) макет заголовка будет выглядеть следующим образом:

Как скрыть/показать панель уведомлений при прокрутке

На экранах от 600 до 899 пикселей, макет будет выглядеть следующим образом:

Как скрыть/показать панель уведомлений при прокрутке

Наконец, на больших экранах (≥900 пикселей) он будет иметь следующий вид:

Как скрыть/показать панель уведомлений при прокрутке

Отметим основные стили:

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

Нижняя часть будет расположена прямо под верхней частью. Как мы увидим чуть позже, мы будем использовать JavaScript для вычисления значения свойства top.

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

Вот связанные стили:

/*CUSTOM VARIABLES HERE*/ .page-header .header-top,
.page-header .header-bottom { position: fixed; left: 0; right: 0; z-index: 1; transition: all 0.4s;
} .page-header .header-top { top: 0; padding: 10px 0; background: var(--pink);
} .page-header .header-bottom { padding: 20px 0; background: var(--white); box-shadow: 0 -2px 10px rgb(0 0 0 / 15%), 0 5px 5px rgba(0, 0, 0, 0.15);
} .page-header .header-bottom .menu { position: absolute; top: 100%; left: 0; right: 0; opacity: 0; visibility: hidden; padding: 15px; border-top: 1px solid whitesmoke; transform: translateY(20px); box-shadow: 0 5px 5px rgba(0, 0, 0, 0.15); background: var(--white); transition: all 0.2s;
} .page-header .header-bottom .menu li:not(:last-child) { margin-bottom: 15px;
} @media (min-width: 900px) { .page-header .header-bottom .menu { position: static; padding: 0; border: none; margin-right: 80px; background: none; box-shadow: none; } .page-header .header-bottom .menu li:not(:last-child) { margin: 0 30px 0 0; }
}

Добавим JavaScript

Для следующего шага добавим поведение в заголовок.

Рассчитаем Offsets

Когда DOM будет готов и когда мы изменим размер окна браузера, сработает функция calculateOffsets(). Эта функция будет отвечать за установку значения свойства top нижней части заголовка и значения свойства padding-top нашего body. Эти действия необходимы, поскольку обе части заголовка являются фиксированными элементами, поэтому они полностью удалены из обычного потока документов. Вот необходимый код JavaScript:

calculateOffsets(); window.addEventListener("resize", () => { calculateOffsets();
}); function calculateOffsets() { const headerTopHeight = headerTop.offsetHeight; const headerBottomHeight = headerBottom.offsetHeight; headerBottom.style.top = `${headerTopHeight}px`; body.style.paddingTop = `${headerTopHeight + headerBottomHeight}px`;
}

Переключим меню

Каждый раз, когда мы нажимаем на кнопку-переключатель, видимость меню меняется. Если меню скрыто, то оно появится, и наоборот. Вот соответствующий код JavaScript:

const menu = document.querySelector(".page-header .header-bottom .menu");
const toggleMenu = document.querySelector( ".page-header .header-bottom .toggle-menu"
); toggleMenu.addEventListener("click", () => { menu.classList.toggle("is-visible");
});

И стили:

.page-header .header-bottom .menu { transition: all 0.2s;
} .page-header .header-bottom .menu.is-visible { opacity: 1; visibility: visible; transform: none;
}

Переключим заголовок панели

Теперь о главной цели этого урока. Каждый раз, когда мы прокручиваем вниз, полоса заголовка должна плавно исчезать и возвращаться в поле зрения, когда мы прокручиваем назад. Чтобы реализовать это, мы будем следовать тому же шаблону, что и в предыдущем руководстве, поэтому мы заимствуем из него приличное количество кода.

По поводу функциональности:

По мере прокрутки вниз объект body получит класс scroll-down. На этом этапе верхняя панель будет анимирована вверх и станет скрытой. При этом нижняя часть будет анимирована выше и займет пустое место, плюс мы пересчитаем значение свойства padding-top.

По мере прокрутки вверх объект body получит класс scroll-up. Обратите внимание, что нам этот класс не понадобится, но он будет в нашем распоряжении, если мы захотим позже изменить демонстрационные стили с помощью CSS. На этом этапе мы удалим преобразования CSS из частей заголовка и снова пересчитаем значение свойства padding-top.

Если мы прокрутим страницу вверх, она потеряет свой scroll-up.

Вот (довольно обширный!) Код JavaScript для обработки всего этого:

const body = document.body;
const headerTop = document.querySelector(".page-header .header-top");
const headerBottom = document.querySelector(".page-header .header-bottom");
const menu = document.querySelector(".page-header .header-bottom .menu");
const toggleMenu = document.querySelector( ".page-header .header-bottom .toggle-menu"
);
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0; window.addEventListener("scroll", () => { const currentScroll = window.pageYOffset; const headerTopHeight = headerTop.offsetHeight; const headerBottomHeight = headerBottom.offsetHeight; if (currentScroll <= 0) { body.classList.remove(scrollUp); return; } if (currentScroll > lastScroll && !body.classList.contains(scrollDown)) { // down body.classList.remove(scrollUp); body.classList.add(scrollDown); headerBottom.style.transform = `translateY(-${headerTopHeight}px)`; body.style.paddingTop = `${headerBottomHeight}px`; } else if ( currentScroll < lastScroll && body.classList.contains(scrollDown) ) { // up body.classList.remove(scrollDown); body.classList.add(scrollUp); headerBottom.style.transform = "none"; body.style.paddingTop = `${headerTopHeight + headerBottomHeight}px`; } lastScroll = currentScroll;
});

И связанные стили:

/*CUSTOM VARIABLES HERE*/ .page-header .header-top,
.page-header .header-bottom { transition: all 0.4s;
} .scroll-down .header-top { transform: translate3d(0, -100%, 0);
}

Заключение

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

Как всегда, большое спасибо за чтение!

Автор: George Martsoukos

Источник: webdesign.tutsplus.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен