Вертикальное фиксированное меню на CSS

Вертикальное меню с круглыми индикаторами, при наведении по которым, появляется панель с иконками и текстом.

Сложность

Основная идея - расположить круглые индикаторы (точки) на краю страницы, которые будут работать в качестве ссылок на разделы страницы.

Дополнительной функцией будет, преобразование точек в панель с иконками, с названием разделов страницы.

Создание разметки

Наше вертикальное меню это неупорядоченный список, расположенный в nav.cd-vertical-nav. Для мобильных устройств, вместо основной навигации, создадим небольшую кнопку с классом button.cd-nav-trigger. Кроме того, каждый элемент навигации добавим в тег section с классом section.cd-section:

<nav class="cd-vertical-nav">
    <ul>
        <li><a href="#section1" class="active"><span class="label">Intro</span></a></li>
        <li><a href="#section2"><span class="label">Events</span></a></li>
        <!-- additional navigation items here -->
    </ul>
</nav><!-- .cd-vertical-nav -->
 
<button class="cd-nav-trigger cd-image-replace">Open navigation<span aria-hidden="true"></span></button>
 
<section id="section1" class="cd-section">
    <div class="content-wrapper">
        <h1>Vertical Fixed Navigation #2</h1>
        <a href="#section2" class="cd-scroll-down cd-image-replace">scroll down</a>
    </div>
</section><!-- cd-section -->
 
<section id="section2" class="cd-section">
    <div class="content-wrapper">
        <!-- контент для секции -->
    </div>
</section><!-- cd-section -->
 
<!-- дополнительные секции -->

Добавление стилей

Для мобильных устройств (меньше 800px), устанавливаем свойство position: fixed для класса .cd-nav-trigger и элемента nav, разместим их в нижнем правом углу страницы.

При нажатии на .cd-nav-trigger, добавляем класс .open к навигации, чтобы изменить её масштаб от 0 до 1, используя CSS3 transition для гладкой анимации.

.cd-nav-trigger {
  display: block;
  position: fixed;
  z-index: 2;
  bottom: 30px;
  right: 5%;
}
 
.cd-vertical-nav {
  position: fixed;
  z-index: 1;
  right: 5%;
  bottom: 30px;
  transform: scale(0);
  transform-origin: right bottom;
  transition: transform 0.2s;
}
.cd-vertical-nav.open {
  transform: scale(1);
}

Для больших экранов, мы используем Modernizr для определения сенсорных устройств (используя классы .touch и .no-touch).
На сенсорных устройствах, боковые элементы вертикального меню (текст и иконки) будут открыты по умолчанию, для не-сенсорных устройств, отображаем их при наведении по точкам.

Задаем фиксированную ширину и высоту для элемента nav, разместим его справой стороны экрана. Для создания фона навигационной панели, используем псевдо-элемент ::before; Для не-сенсорных устройств, псевдо-элемент ::before разместим за пределами экрана и при наведении передвигаем его к правому краю экрана. То же самое происходит с элементами span.label.

@media only screen and (min-width: 800px) {
  .cd-vertical-nav {
    right: 0;
    top: 0;
    height: 100vh;
    width: 90px;
  }
  .cd-vertical-nav::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.8);
    transform: translateX(100%);
    transition: transform 0.4s;
  }
  .no-touch .cd-vertical-nav:hover::before, 
  .touch .cd-vertical-nav::before {
    transform: translateX(0);
  }
  .cd-vertical-nav .label {
    display: block;
    transform: translateX(100%);
    transition: transform 0.4s;
  }
  .no-touch .cd-vertical-nav:hover .label, 
  .touch .cd-vertical-nav .label {
    transform: translateX(0);
  }
}

Для создания иконок и точек навигации, используем псевдо-элементы ::before и ::after. Для не-сенсорных устройств, ::before и ::after по умолчанию отображаются в качестве точек, а при наведении масштабируем с появлением иконок и текста. Пример такого отображения вы можете увидеть на сайте http://www.apple-services.ru.

@media only screen and (min-width: 800px) {
  .cd-vertical-nav a {
    position: relative;
    padding: 3em 0 0;
    margin: 1.4em auto;
  }
  .cd-vertical-nav a::before, 
  .cd-vertical-nav a::after {
    content: '';
    position: absolute;
    left: 50%;
    transition: transform 0.4s 0s;
  }
  .cd-vertical-nav a::before {
    /* filled circle */
    top: 0;
    height: 32px;
    width: 32px;
    border-radius: 50%;
    background: #eaf2e3;
    transform: translateX(-50%) scale(0.25);
  }
  .cd-vertical-nav a::after {
    /* icon */
    top: 8px;
    height: 16px;
    width: 16px;
    background: url(../img/cd-nav-icons.svg) no-repeat;
    transform: translateX(-50%) scale(0);
  }
  .no-touch .cd-vertical-nav:hover a::before, 
  .no-touch .cd-vertical-nav:hover a::after, 
  .touch .cd-vertical-nav li:nth-of-type(n) a::before, 
  .touch .cd-vertical-nav li:nth-of-type(n) a::after {
    transform: translateX(-50%) scale(1);
  }
}

Теперь сложная часть: при масштабировании, точки находятся слишком далеко друг от друга. Мы можем уменьшить это расстояние переместив их по оси Y.

Давайте начнем с центральных точек (в нашем случае, вторая и третья); нам нужно переместить вторую точку вниз (используем положительное значение translateY), в этот момент, перемещаем третью точку вверх (используем отрицательное значение translateY):

.cd-vertical-nav li:nth-of-type(2) a::after {
    transform: translateX(-50%) translateY(1.5em) scale(0);
  }
  .cd-vertical-nav li:nth-of-type(2) a::before {
    transform: translateX(-50%) translateY(1.5em) scale(0.25);
  }
  .cd-vertical-nav li:nth-of-type(3) a::after {
    transform: translateX(-50%) translateY(-1.5em) scale(0);
  }
  .cd-vertical-nav li:nth-of-type(3) a::before {
    transform: translateX(-50%) translateY(-1.5em) scale(0.25);
  }

Теперь для первой точки: берем значение второй точки, умножаем на 3. То же самое и для четвертой: берем значение третей точки и умножаем на 3.

.cd-vertical-nav li:first-of-type a::after {
    transform: translateX(-50%) translateY(4.5em) scale(0);
  }
  .cd-vertical-nav li:first-of-type a::before {
    transform: translateX(-50%) translateY(4.5em) scale(0.25);
  }
  .cd-vertical-nav li:nth-of-type(4) a::after {
    transform: translateX(-50%) translateY(-4.5em) scale(0);
  }
  .cd-vertical-nav li:nth-of-type(4) a::before {
    transform: translateX(-50%) translateY(-4.5em) scale(0.25);
}

Если у вас другое количество элементов навигации, то тогда у вас будут другие значения. Например, если у вас есть шесть элементов, начинайте также от центральных точек (в данном случае, третья и четвертая), вы можете присвоить им значение translateX 1,5em/-1.5em; затем значения для второй и пятой точки translateX в 4.5em/-4.5em (3*1,5), и наконец, значения для первой и шестой точки translateY в 7.5em/-7.5em (5*1,5).

Если у вас нечетное число элементов вертикального меню, скажем 5, вы не трогаете центральную точку (в данном случае третью). Затем присваиваете значение translateY 3em/-3em (2*1,5) для второй и четвертой точки, и значение translateX 6em/-6em (4*1.5) для первой и пятой точки.

Обработка событий

Когда пользователь прокручивает разделы, функция updateSections(), определяет текущий раздел и присваивает класс .active для соответствующего пункта вертикального меню.
Кроме того, мы обрабатываем событие нажатия на button.cd-nav-trigger , чтобы открыть/закрыть вертикальное меню на мобильных устройствах.

ДЕМО СКАЧАТЬ

 

Перевод статьи Vertical Fixed Navigation #2

Тэги: transitionresponsivenavigation

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.