Найти в Дзене
in9var

Создаем крутой лендинг сайт с нуля: анимированное burger меню #12

Привет! Сегодня сделаем мобильное анимированное меню для нашего лендинга, применим библиотеку framer-motion (motion) для красивого эффекта открытия. Будет интересно, погнали! Полезные ссылки: Часть 1. Подготовка и настройка проекта Часть 2. Настройка конфигурации и установка необходимых библиотек Часть 3. Создание CSS-переменных и верстка блока Header Часть 4. Верстка секции Hero, создание компонента Button Часть 5. Верстка секции About Часть 6. Верстка секции Gallery Часть 7. Верстка секции WhyUs Часть 8. Верстка секции Catalogue Часть 9. Верстка секции Map Часть 10. Верстка секции Footer Часть 11. Создание якорных ссылок, рефакторинг Часть 12. Создание мобильного меню Часть 13. Анимация секций при скролле Часть 14. Установка метаданных Часть 15. Настройка Favicon.ico Часть 16. Настройка счетчика Яндекс Метрики Часть 17. Публикуем проект на хостинге Чтобы не писать лишний код анимации, можно воспользоваться пакетом hamburger-react, который предоставляет нам анимированное меню с обраб
Оглавление

Привет! Сегодня сделаем мобильное анимированное меню для нашего лендинга, применим библиотеку framer-motion (motion) для красивого эффекта открытия. Будет интересно, погнали!

Превью | Канал dzen.ru/in9var
Превью | Канал dzen.ru/in9var

Полезные ссылки:

Часть 1. Подготовка и настройка проекта

Часть 2. Настройка конфигурации и установка необходимых библиотек

Часть 3. Создание CSS-переменных и верстка блока Header

Часть 4. Верстка секции Hero, создание компонента Button

Часть 5. Верстка секции About

Часть 6. Верстка секции Gallery

Часть 7. Верстка секции WhyUs

Часть 8. Верстка секции Catalogue

Часть 9. Верстка секции Map

Часть 10. Верстка секции Footer

Часть 11. Создание якорных ссылок, рефакторинг

Часть 12. Создание мобильного меню

Часть 13. Анимация секций при скролле

Часть 14. Установка метаданных

Часть 15. Настройка Favicon.ico

Часть 16. Настройка счетчика Яндекс Метрики

Часть 17. Публикуем проект на хостинге

  • Демо–проект лендинга можно посмотреть по ссылке.
  • Шаблон лендинга, который мы будем делать, доступен в Figma по ссылке.
  • Код данного урока доступен в репозитории GitHub по ссылке.
  • В моём блоге этот урок в удобном для чтения виде по ссылке.

Устанавливаем пакет hamburger-react

Чтобы не писать лишний код анимации, можно воспользоваться пакетом hamburger-react, который предоставляет нам анимированное меню с обработчиком закрытия, отслеживанием состояния и небольшой кастомизацией в виде указания цвета и размера иконки.

Стиль анимации выбирается при импорте модуля, в нашем случае это squash.

Для установки в консоль вводим команду.

npm i hamburger-react

Создаем компонент MobileMenu.jsx

Создадим блок мобильного меню, для этого в папке /app/components/blocks/ создаем файл MobileMenu.jsx.

Содержимое файла MobileMenu.jsx

import Link from 'next/link';
import { motion } from 'motion/react';
export default function MobileMenu({ close }) {
return (
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0, transition: { duration: 0.2 } }}
transition={{ duration: 0.3 }}
className='absolute inset-0 bg-secondary text-on-secondary z-40'
>
<div className='flex flex-col items-center gap-10 pt-40 pb-10 px-10 text-2xl font-bold uppercase'>
<Link href={'#products'} onClick={() => close()}>
Наша продукция
</Link>
<Link href={'#about'} onClick={() => close()}>
О нас
</Link>
<Link href={'#contacts'} onClick={() => close()}>
Контакты
</Link>
</div>
</motion.div>
);
}

Это обычный блок верстки с абсолютным позиционированием, перекрывающий всё окно.

Для того чтобы была возможность использовать кнопку меню для закрытия, я добавил z-index в это меню, а также в контейнер значка мобильного меню.

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

Обработчик события onClick необходим для закрытия меню при клике по нему, а также для удаления стиля style="overflow: hidden;" с корневого контейнера. Добавлять данный стиль мы будем в компоненте Header.jsx.

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

Рефакторинг блока Header.jsx

Содержимое файла Header.jsx

'use client';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import Logo from '../elements/Logo';
import SocialIcons from './SocialIcons';
import { Squash as Hamburger } from 'hamburger-react';
import MobileMenu from './MobileMenu';
import { AnimatePresence } from 'motion/react';
export default function Header() {
const [isOpen, setIsOpen] = useState(false);
const menuToggleHandler = () => setIsOpen(!isOpen);
const menuCloseHandler = () => setIsOpen(false);
useEffect(() => {
if (isOpen) document.documentElement.style.overflow = 'hidden';
return () => {
document.documentElement.style.overflow = '';
};
}, [isOpen]);
return (
<>
<header className='flex justify-between lg:h-20 mt-7'>
<div className='flex grow flex-col lg:flex-row lg:justify-between lg:items-center gap-2'>
<Logo href={'/'} />
<div className='flex flex-col lg:flex-row lg:justify-between lg:items-center gap-2 lg:gap-12'>
<nav className='hidden lg:block'>
<ul className='flex gap-12 font-light'>
<li>
<Link href={'#products'}>Наша продукция</Link>
</li>
<li>
<Link href={'#about'}>О нас</Link>
</li>
<li>
<Link href={'#contacts'}>Контакты</Link>
</li>
</ul>
</nav>
<span className='font-black'>+7 999 888 88 88</span>
<SocialIcons />
</div>
</div>
<div className='block lg:hidden z-50'>
<Hamburger toggled={isOpen} size={36} toggle={menuToggleHandler} color='hsl(var(--color-background))' />
</div>
</header>
<AnimatePresence>{isOpen && <MobileMenu close={menuCloseHandler} />}</AnimatePresence>
</>
);
}

Импортируем компонент Hamburger, который будет значком меню нашего лендинга в мобильном разрешении, и задаём ему необходимые параметры.

Для работы нам необходимо хранить состояние открытия меню — isOpen, а также два обработчика — переключатель открытия меню и закрытие меню.

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

Хук useEffect необходим для установки style="overflow: hidden;" страницы, чтобы предотвратить скроллинг при открытом меню.

Конструкция <AnimatePresence>...</AnimatePresence> необходима для отображения анимации компонента как при открытии, так и при закрытии, без этого при закрытии меню будет резко исчезать.

В dev-режиме, мы получим вот такой блок нашего сайта:

-2
-3

В следующих статьях займемся анимациями секций при скролле страницы.

Код данного урока доступен в репозитории GitHub по ссылке.

Не забудь подписаться на канал, а также заходи на мой блог blog.in9var.ru, а также можешь посетить мой основной сайт — in9var.ru.