Найти в Дзене
Журнал «Код»

Улучшаем контекстное меню: делаем стильно и красиво

Оглавление

Почти как настоящее

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

-2

Готовим страницу

В предыдущем проекте мы на страницу добавили только пустой блок, а всё остальное делали через скрипт. Это не очень удобно — если нужно добавить или убрать какие-то элементы, надо идти в скрипт и править всё там. На этот раз сделаем иначе — сверстаем контекстное меню как часть страницы, а потом в скрипте скроем его.

Чтобы меню получилось красивым, сразу подключим новый шрифт и нормализатор — он уберёт всё лишнее оформление в браузерах и позволит нам настраивать внешний вид по своему усмотрению.

Наполним наше меню и используем для этого список, как и прошлый раз. Но если тогда мы делали единое меню, то сейчас добавим разделы — они будут отделяться друг от друга и группировать по смыслу разные пункты меню. Для этого добавим к каждому такому списку класс "menu-list". Внутрь этого списка мы сложим все элементы нашего меню, причём у каждого элемента списка будет класс "menu-item" — так мы сможем настраивать внешний вид всех элементов.

А теперь сложная часть: каждый пункт меню сделаем кнопкой — так мы сможем легко обрабатывать нажатия и группировать визуальные элементы в меню. Сначала в кнопку мы положим иконку c помощью тега <i> — он устанавливает курсивное начертание текста, но текста в нём не будет, только иконка. После этого мы пишем название кнопки и закрываем тег кнопки.

Чтобы было понятнее, разберём первый элемент максимально подробно:

-3

На странице появились две кнопки со стандартным оформлением — это нормально, потому что мы ещё не настраивали стили. Но на кнопках нет иконок, которые мы прописывали в теге <i>, — а всё потому, что браузер ничего не знает про эти иконки и откуда их брать. Чтобы это исправить, используем js-библиотеку иконок Feather, которая работает так:

  1. Мы на странице указываем название иконки, которую хотим получить, с помощью свойства data-feather, например data-feather="edit-2"
  2. Потом подключаем библиотеку на странице:
      <script src='https://unpkg.com/feather-icons@4.29.0/dist/feather.min.js'></script>
  3. А затем подключаем свой скрипт script.js и в нём пишем команду:
    feather.replace();
  4. Эта команда находит на странице все ссылки на иконки и меняет их на SVG-картинки.

Сделаем всё это и посмотрим на результат:

-4

Точно так же, по разделам, сделаем всё остальное меню. Единственное, что нам понадобится дополнительно — это новый список с классом «menu-sub-list» для вложенного меню. Читайте комментарии в коде, чтобы было проще понять, что происходит на странице:

У нас есть все пункты меню, но на контекстное меню это совсем не похоже. Исправим это с помощью стилей
У нас есть все пункты меню, но на контекстное меню это совсем не похоже. Исправим это с помощью стилей

Настраиваем стили

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

Также сразу добавим блок c CSS-переменными — так мы сможем настраивать все цвета на странице в одном месте — и подключим новый шрифт:

Теперь элементы меню лучше заметны на странице, но до идеала пока далеко
Теперь элементы меню лучше заметны на странице, но до идеала пока далеко

Настраиваем меню и разделы

Сделаем из нашего простого списка кнопок что-то похожее на меню: добавим подложку со скруглёнными краями, тени и разделители между разделами.

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

Стало немного аккуратнее, но работы ещё много
Стало немного аккуратнее, но работы ещё много

Скрываем вложенное меню

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

-8

Настраиваем внешний вид кнопок

Сейчас кнопки в меню выглядят как кнопки, а так быть не должно. Добавим в стили настройки кнопок: уберём границы, сделаем тот же фон, что у подложки, и настроим отступы:

-9

Вроде хорошо, но иконки всё ещё слишком близко к тексту. А ещё они того же цвета, что и текст, а так быть не должно — сделаем их серыми:

Намного лучше
Намного лучше

Добавляем выделение элемента при наведении мышки

Чтобы явно выделить нужный элемент меню при выборе, добавим ему свой фон и сделаем иконку более заметной — раскрасим её в цвет текста. Так будет сразу понятно, с каким пунктом мы работаем. Заодно добавим красный цвет на пункт «Удалить» при наведении:

-11
-12

Раскрашиваем иконки во вложенном меню

Последнее, что нам осталось сделать в стилях, — раскрасить иконки во вложенном меню. Используем для этого цвета из глобальных переменных, которые мы описали в самом начале:

-13

Пишем скрипт

Сейчас меню выглядит красиво, но его сразу видно на странице и оно не работает как контекстное меню. Настоящее контекстное меню пока никуда не исчезло:

-14
Контекстное меню браузера всё ещё работает
Контекстное меню браузера всё ещё работает

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

Обратите внимание — мы передаём координаты top и left в стили, чтобы контекстное меню появилось именно там, где мы щёлкнули мышкой, а не просто в левом верхнем углу.

-16

Посмотреть работу меню на странице проекта.