Создаем выпадающее боковое меню на HTML, CSS и JavaScript
![Создаем выпадающее боковое меню на HTML, CSS и JavaScript](/images/articles/js-dropdown-menu-p1.png)
Доброго времени суток! В данной статье мы рассмотрим с Вами как сделать боковое меню с выпадающим подменю, причем состояние меню будет сохраняться при перезагрузке страницы. Реализация будет на чистом 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, изменяя таким образом стиль элемента и запоминая его состояние в локальном хранилище.
Таким образом, код создает боковое меню с поддержкой сохранения состояния открытия/закрытия подменю с использованием локального хранилища браузера.
-
-
Михаил Русаков
Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.