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

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

Наша цель — иметь приложение, которое точно соответствует приведенному ниже GIF к концу руководства:

Настройка проекта

Поскольку наш проект минимален, нам не потребуется много внешних инструментов: в нашей системе установлены Node.js и React.
Для начала запустите следующий код в своем терминале:

npx create-react-app project
cd project
npm start

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

Этот макет будет выполнен путем объединения правил позиционирования из CSS и Flexbox.

Нам нужен стартер, поэтому вот как должен выглядеть наш App.js:

import React from 'react';
import './App.css';

function App() {
 return(  
   <div>
   </div>
 )

}

export default App;

Создайте папку для компонентов с компонентом Navbar.js и нашим Navbar.css. Вот как должен выглядеть наш компонент навигационной панели:

import React from 'react';
import './Navbar.css';
function Navbar() {
  return (
        <nav className="Navbar">
            <span className='nav-logo'>
                <h2>Open Replay</h2>
            </span>
            <div className="nav-items">
                <a href="/Home">Home</a>
                <a href="/About">About</a>
                <a href="/Service">Service</a>
                <a href="/Contact">Contact</a>
            </div>
        </nav>

  )
}
export default Navbar

Мы импортируем этот файл в наш компонент App.js, чтобы увидеть, как он отображается в нашем браузере.
У нас должно получиться следующее:

Чтобы наше демо-приложение выглядело одинаково, нам нужно добавить стили ниже, импортировав стили из navbar.css:

.Navbar {
    height: 60px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: blueviolet;
}
.Navbar .nav-logo {
    font-weight: 700;
    font-size: 21px;
    margin: 15px;
    color: #fff;
}
.Navbar>.nav-items>a {
    color: #fff;
    font-size: 16px;
    text-decoration: none;
    margin: 15px;
    position: relative;
    opacity: 0.9;
}

У нас должно получиться это после стиля:

Чтобы добавить нашу маленькую анимацию при наведении, как показано в демо, добавьте это в свой CSS:

.Navbar>.nav-items>a:hover {
    opacity: 1;
}
.Navbar>.nav-items>a::before {
    content:"  ";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 0;
    height: 3px;
    background: #fff;
    transition: all .45s;
}
.Navbar>.nav-items>a:hover::before {
    width: 100%;
}

Мы должны запустить его:

Повтор сеанса с открытым исходным кодом

OpenReplay – это пакет для воспроизведения сеансов с открытым исходным кодом, который позволяет вам видеть, что пользователи делают в вашем веб-приложении, помогая вам быстрее устранять неполадки. OpenReplay размещается на собственном сервере для полного контроля над вашими данными.

Начните получать удовольствие от отладки — начните использовать OpenReplay бесплатно.

Гамбургер Навбар

Используя адаптивный дизайн, онлайн-ресурсы создаются таким образом, что способ их отображения зависит от устройства, с которого они доступны. Обычно применяется философия «сначала мобильные», означающая, что опыт сначала разрабатывается для небольших экранов, таких как смартфоны и планшеты, а затем масштабируется для больших дисплеев.

Панель навигации часто имеет два представления: увеличенное и скрытое. Нам нужен новый элемент для нашего переключателя, чтобы он работал над частью нашей панели навигации, отвечающей за гамбургер. Это будет ниже нашего элемента навигации в нашем компоненте navbar.js, который будет классом с именем nav toggle; это будет использоваться для создания нашего гамбургера:

<div className="nav-toggle">
  <div className="bar">

  </div>
</div>

Функция CSS, называемая медиа-запросами, позволяет вам описать, как ваш макет контента должен реагировать на определенные обстоятельства, такие как изменение ширины области просмотра.
Целевой тип мультимедиа и точка останова, в которой применяются стили, записываются после правила@media. в запросах:

@media screen and (max-width: 700px) {
  // the rules go here
}

Мы можем добавить этот CSS, чтобы увидеть, является ли он отзывчивым:

Мы скрываем элемент ul со свойством display: none:

.Navbar>.nav-toggle {
  display: none;
}

В приведенном выше коде мы устанавливаем отображение нашей навигации-гамбургера на none, потому что мы хотим, чтобы она была видна только на небольших экранах.

Теперь мы можем указать CSS, что делать, когда размер экрана уменьшается:

@media (max-width: 700px) {
  .nav-toggle {
    display: flex;  
    width: 40px;
    height: 40px;
    align-items: center;
    justify-content: center;
    cursor: pointer;
  }
  .nav-toggle>.bar {
    position: relative;
    width: 32px;
    height: 2px;
    background: #fff;
  }
}

Чтобы заставить наш гамбургер работать, мы заменим наши адаптивные стили следующим:

 @media (max-width: 700px) {
            .Navbar>.nav-items {
                display: flex;
                flex-direction: column;
                background: #3b4da7;
                position: absolute;
                top: 50px;
                left: 0;
                height: 100%;
                width: 100%;
                transform: translateX(-100%);
                transition: all .40s;
            }
            .Navbar>.nav-items>a::before {
                background: transparent;
            }
            .Navbar>.nav-items.open {
                transform: translateX(0);
            }
            .Navbar>.nav-toggle {
                display: flex;
                width: 60px;
                height: 60px;
                align-items: center;
                justify-content: center;
                cursor: pointer;
            }
            .nav-toggle>.bar {
                position: relative;
                width: 32px;
                height: 2px;
                background: #ffffff;
                transition: all 0.45s ease-in-out;
            }
            .nav-toggle>.bar::before,
            .nav-toggle>.bar::after {
                content:"  ";
                position: absolute;
                height: 2px;
                background: #ffffff;
                border-radius: 2px;
                transition: all 0.45s ease-in-out;
            }
            .nav-toggle>.bar::before {
                transform: translateY(-8px);
                width: 30px;
                right: 0;
            }
            .nav-toggle>.bar::after {
                width: 30px;
                transform: translateY(8px);
            }
            .nav-toggle.open>.bar {
                transform: translateX(-40px);
                background: transparent;
            }
            .nav-toggle.open>.bar::before {
                width: 32px;
                transform: rotate(45deg) translate(26px, -26px);
            }
            .nav-toggle.open>.bar::after {
                transform: rotate(-45deg) translate(26px, 26px);
            }
        }

Все, что мы сделали, это стилизовали гамбургер и сделали так, чтобы он соответствовал отзывчивости.

Для нашей функции переключения, которую довольно легко воспроизвести, мы заменим наш компонент navbar.js приведенным ниже кодом. В нашем коде мы устанавливаем начальное состояние в false; затем мы используем оператор if для нашей логики и передаем функцию onclick, чтобы наше гамбургер-меню переключалось всякий раз, когда на него нажимают.

import React, { useState } from "react";
import "./Navbar.css";
const Navbar = () => {
  const [Open, setOpen] = useState(false);
  return (
    <nav className="Navbar">
      <span className="nav-logo">Open Replay Blog</span>
      <div className={`nav-items ${Open && "open"}`}>
        <a href="/home">Home</a>
        <a href="/about">About</a>
        <a href="/Blog Page">Blog Page</a>
        <a href="/contact">Contact</a>
      </div>
      <div
        className={`nav-toggle ${Open && "open"}`}
        onClick={() => setOpen(!Open)}
      >
        <div className="bar"></div>
      </div>
    </nav>
  );
};
export default Navbar;

У нас должно быть это в конце кода;

Липкая функциональность

Для прилипания импортируйте useEffect и замените наш код следующим:

import React, { useState, useEffect } from "react";
import "./Navbar.css";
const Navbar = () => {
  const [Open, setOpen] = useState(false);
  const[sticky, setSticky]=useState();

  useEffect(()=>{
    const handleScroll=()=>setSticky(window.scrollY>200)
    console.log(window.scrollY)
    window.addEventListener('scroll', handleScroll)
    return()=> window.removeEventListener('scroll', handleScroll)
  })

  return (
    <nav className={`${sticky ? "sticky" : ""}`}>
    <div className="Navbar" >
      <span className="nav-logo">Open Replay Blog</span>
      <div className={`nav-items ${Open && "open"}`}>
        <a href="/home">Home</a>
        <a href="/about">About</a>
        <a href="/Blog Page">Blog Page</a>
        <a href="/contact">Contact</a>
      </div>
      <div
        className={`nav-toggle ${Open && "open"}`}
        onClick={() => setOpen(!Open)}
      >
        <div className="bar"></div>
      </div>
    </div>
</nav>
  );
};
export default Navbar;

Объяснение кода: мы устанавливаем для нашего состояния sticky значение false. В нашем useEffect у нас была объявлена ​​функция прокрутки дескриптора. В нем у нас есть логика, которая гласит, что если window.scrollY больше 200, установите для sticky значение true, иначе оно будет ложным. Мы добавили событие прокрутки непосредственно под ним, и, наконец, чтобы избежать утечки памяти, мы использовали этот код: return()=> window.removeEventListener('scroll', handleScroll). Мы обернули наш div в nav element и добавили className с логикой JS, которая указывает, верно ли это, затем добавляем класс «липкий», а если нет, делаем иначе.

В нашем CSS у нас должно быть это:

Чтобы показать нашу панель навигации в лучшем виде, мне пришлось создать компонент для текста с именем Text.js и импортировать его в наш App.js. В этом компоненте я ввел длинный текст, чтобы активировать жест прокрутки браузера. У нас должно получиться это в конце урока:

Заключение

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

СОВЕТ ОТ РЕДАКТОРА. Чтобы по-новому взглянуть на адаптивные компоненты, не пропустите нашу статью Создание адаптивных веб-страниц с помощью React-Responsive и TypeScript.

Первоначально опубликовано на blog.openreplay.com 8 декабря 2022 г.