Создаем выпадающее боковое меню на HTML, CSS и JavaScript

0

Создаем выпадающее боковое меню на HTML, CSS и JavaScript

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

Итак, код:


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Autoclose menu</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">

    <style>
        *,
        *::after,
        *::before {
            box-sizing: border-box;
        }

        html,
        body {
            margin: 0;
            padding: 0;
            min-height: 100vh;
        }

        .container {
            display: flex;
            background-color: bisque;
            min-height: 100vh;
        }

        .sidebar-menu {
            padding: 5px 0;
            background-color: rgb(214, 214, 214);
            min-width: 180px;
        }

        .content {
            padding: 5px;
            background-color: burlywood;
            flex-grow: 1;
        }

        ul {
            list-style-type: none;
            padding-left: 0;
        }

        .menu {
            margin: 0;
        }

        .menu-item {}

        .submenu-item {
            padding: 5px 8px;
        }

        .menu-item__header {
            padding: 5px 8px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .menu-item__header:hover,
        .submenu-item:hover {
            background-color: beige;
        }

        .menu-item__header::after {
            font-family: "Bootstrap-icons";
            content: "F282";
            transition: transform 0.3s linear;
        }

        .menu-item__header-open::after {
            font-family: "Bootstrap-icons";
            content: "F282";
            transform: rotate(180deg);
        }

        .submenu {
            padding-left: 0;
            transition: max-height 0.3s ease-in-out;
            max-height: 0;
            overflow: hidden;
        }

        .menu-item__header-open+.submenu {
            max-height: 500px;
        }

        .submenu-item {}
    </style>

</head>

<body>
    <div class="container">
        <aside class="sidebar-menu" id="sidebarmenu">
            <ul class="menu">
                <li class="menu-item">
                    <div class="menu-item__header">Входящие</div>
                    <ul class="submenu">
                        <li class="submenu-item">
                            <a href="">Ссылка номер №1</a>
                        </li>
                        <li class="submenu-item">item 2</li>
                        <li class="submenu-item">item 3</li>
                        <li class="submenu-item">item 4</li>
                        <li class="submenu-item">item 5</li>
                    </ul>
                </li>
                <li class="menu-item">
                    <div class="menu-item__header">Исходящие</div>
                    <ul class="submenu">
                        <li class="submenu-item">item 1</li>
                        <li class="submenu-item">item 2</li>
                        <li class="submenu-item">item 3</li>
                        <li class="submenu-item">item 4</li>
                        <li class="submenu-item">item 5</li>
                    </ul>
                </li>
                <li class="menu-item">
                    <div class="menu-item__header">Другие</div>
                    <ul class="submenu">
                        <li class="submenu-item">item 1</li>
                        <li class="submenu-item">item 2</li>
                        <li class="submenu-item">item 3</li>
                        <li class="submenu-item">item 4</li>
                        <li class="submenu-item">item 5</li>
                    </ul>

                </li>
            </ul>
        </aside>
        <main class="content">
            Some content goes here
        </main>
    </div>

    <script>

    // Функция для обработки событий в боковом меню
    function initSidebarMenu(
        settingsKey = '__sidebarMenu_',   // Ключ для сохранения состояния в локальном хранилище
        menu_id = 'sidebarmenu',          // ID корневого элемента бокового меню
        menu_item_header_class = 'menu-item__header', // Класс заголовков элементов меню
        menu_item_header_open_class = 'menu-item__header-open' // Класс для открытых подменю
    ) 
    {
        // Вспомогательная функция для преобразования строки в хэш
        const toHex = (string) => string.substring(0, 16).split('').map(char => char.charCodeAt(0)).join('');
        // Функция для генерации уникального ключа на основе текста элемента меню
        const keyHash = (key) => settingsKey + toHex(key);

        // Получение элемента бокового меню и заголовков элементов
        const menu = document.getElementById(menu_id);
        const menuItemHeaders = menu.getElementsByClassName(menu_item_header_class);

        // Перебор заголовков и установка состояния открытия/закрытия для каждого
        for (const itemHeader of menuItemHeaders) {
            const state = JSON.parse(localStorage.getItem(keyHash(itemHeader.innerText)));

            if (state) {
                itemHeader.classList.add(menu_item_header_open_class);
            }
        }

        // Добавление обработчика события для бокового меню
        menu.addEventListener('click', function (e) {
            const element = e.target;
            // Проверка, является ли элемент заголовком элемента меню
            if (element.classList.contains(menu_item_header_class)) {
                // Переключение класса для изменения стиля и сохранение состояния в локальном хранилище
                const state = element.classList.toggle(menu_item_header_open_class);
                localStorage.setItem(keyHash(element.innerText), state);
            }
        });
    }

    // Вызов функции инициализации бокового меню при загрузке страницы
    initSidebarMenu();

    </script>
</body>

</html>

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

Теперь рассмотрим код по частям:

HTML-разметка

  • Есть боковое меню с тремя категориями: «Входящие», «Исходящие», «Другие».
  • В каждой категории есть подменю с пятью элементами.
  • Главное содержимое находится в блоке .
  • CSS-стили

  • Определены стили для бокового меню, заголовков и подменю.
  • Используются иконы Bootstrap для стрелок, обозначающих состояние открытия/закрытия подменю.
  • Применены стили для анимации изменения цвета при наведении и анимации открытия/закрытия подменю.
  • JavaScript-скрипт

  • Функция initSidebarMenu инициализирует боковое меню.
  • Используется локальное хранилище браузера для сохранения состояния открытия/закрытия подменю. Ключи для хранения состояния генерируются на основе текста заголовков элементов меню.
  • При загрузке страницы функция проверяет сохраненное состояние и автоматически открывает подменю для соответствующих элементов.
  • Когда пользователь кликает на заголовок элемента меню, скрипт переключает класс menu-item__header-open, изменяя таким образом стиль элемента и запоминая его состояние в локальном хранилище.

    Таким образом, код создает боковое меню с поддержкой сохранения состояния открытия/закрытия подменю с использованием локального хранилища браузера.

    Источник

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.