У каждого веб-сайта есть меню, которое как правило располагается в шапке. Для удобного пользовательского опыта мы должны давать возможность быстро перемещаться по сайту и часто для этого используется меню, прилипающее к верхнему краю экрана. Но что если мы хотим чтобы пользователь не отвлекался на лишние элементы, а меню не занимало ценное на странице место.
Сделаем так, чтобы при скролле вверх наше меню плавно появлялось, а при прокрутке вниз – плавно скрывалось. Можно частично использовать основу из статьи про то, как сделать плавающее меню на Javascript:
<header id="header" class="header"></header>
<nav id="nav" class="nav">
<ul class="nav-wr">
<li class="nav-item">
<a class="nav-link" href="">
<span>Menu item</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">
<span>Menu item</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">
<span>Menu item</span>
</a>
</li>
</ul>
</nav>
<main id="main" class="main">Content</main>
CSS стили:
/* Сбросим дефолтные отступы */
body{
margin: 0;
padding: 0;
}
.header{
background: #FFFACD;
width: 100%;
height: 100px;
}
.nav{
background: #87CEEB;
width: 100%;
height: 50px;
overflow: hidden;
display: flex;
justify-content: space-around;
}
.main{
background: #AFEEEE;
width: 100%;
height: 150vh;
display: block;
}
.nav-wr{
display: flex;
list-style: none;
padding: 0;
margin: 0;
}
.nav-item{
margin: 0 10px;
display: flex;
}
.nav-link{
display: flex;
align-items: center;
text-decoration: none;
}
.menu-sticky-hidden{
position: fixed;
top: 0;
height: 0;
transition: none;
}
.menu-sticky-hidden + .main{
padding-top: 50px;
}
.menu-sticky-visible{
position: fixed;
top: 0;
height: 50px;
transition: all ease-out 0.2s;
}
.menu-sticky-visible + .main{
padding-top: 50px;
}
.menu-animation{
transition: all ease-out 0.2s;
}
Сложность задачи заключается в том, чтобы сделать все этапы появления/скрытия меню плавными с помощью css-свойства transition. Получается, что для одного и того же интервала при разном направлении прокрутки нам необходимо задавать разные значения position и стили с определенной специфичностью.
Для этого будем присваивать меню три CSS класса в зависимости от состояния прокрутки в данный момент:
var nav = document.getElementById("nav");
var header = document.getElementById("header");
var headerHeight = header.clientHeight;
var lastTopOffset = 0;
window.onscroll = function() {
var pageOffset = window.pageYOffset;
if ( pageOffset > (headerHeight + 70) ) {
nav.classList.add("menu-animation");
} else {
nav.classList.remove("menu-animation");
}
if ( pageOffset > (headerHeight + 50) ) {
nav.classList.add("menu-sticky-hidden");
} else {
nav.classList.remove("menu-sticky-hidden");
}
if (pageOffset < lastTopOffset) {
if ( pageOffset > headerHeight ) {
nav.classList.add("menu-sticky-visible");
} else {
nav.classList.remove("menu-sticky-visible");
}
} else {
nav.classList.remove("menu-sticky-visible");
}
lastTopOffset = pageOffset;
};
Значение 50 - это высота нашего меню, значение 70 - это высота меню + 20 условных пикселей, которые нужны для того, чтобы при резкой прокрутке вниз CSS класс .menu-sticky-hidden успел добавиться в меню раньше .menu-animation и меню не сделало transition от 50 до 0 пикселей своей высоты.
« список статей