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

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

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

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

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

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

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

<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Стильное контекстное меню</title>
  <!-- подключаем новый шрифт -->
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
  <!-- подключаем нормализатор CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">

  <!-- подключаем свои стили -->
  <link rel="stylesheet" href="style.css">

</head>
<body>
  <!-- всё меню будет в этом блоке -->
  <div class="menu">
    
  </div>

</body>
</html>

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

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

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

<!-- всё меню будет в этом блоке -->
<div class="menu">
  <!-- первый раздел в меню -->
  <ul class="menu-list">
    <!-- список с элементами меню -->
    <li class="menu-item">
      <!-- каждый пункт меню — это кнопка -->
      <button class="menu-button">
        <!-- иконка -->
        <i data-feather="corner-up-right"></i>
          <!-- название пункта меню -->
          Поделиться
      </button>
    </li>
    <!-- начался новый пункт меню -->
    <li class="menu-item"><button class="menu-button"><i data-feather="edit-2"></i>Переименовать</button></li>
  </ul>
</div>

На странице появились две кнопки со стандартным оформлением — это нормально, потому что мы ещё не настраивали стили. Но на кнопках нет иконок, которые мы прописывали в теге <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-картинки.

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

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

<!-- всё меню будет в этом блоке -->
<div class="menu">
  <!-- первый раздел в меню -->
  <ul class="menu-list">
    <!-- список с элементами меню -->
    <li class="menu-item">
      <!-- каждый пункт меню — это кнопка -->
      <button class="menu-button">
        <!-- иконка -->
        <i data-feather="corner-up-right"></i>
          <!-- название пункта меню -->
          Поделиться
      </button>
    </li>
    <!-- начался новый пункт меню -->
    <li class="menu-item"><button class="menu-button"><i data-feather="edit-2"></i>Переименовать</button></li>
  </ul>

  <!-- второй раздел -->
  <ul class="menu-list">
    <li class="menu-item"><button class="menu-button menu-button--black"><i data-feather="circle"></i>Статус<i data-feather="chevron-right"></i></button>
    <!-- делаем вложенное меню -->
      <ul class="menu-sub-list">
        <li class="menu-item"><button class="menu-button menu-button--orange"><i data-feather="square"></i>В работе</button></li>
        <li class="menu-item"><button class="menu-button menu-button--purple"><i data-feather="octagon"></i>На паузе</button></li>
        <li class="menu-item"><button class="menu-button menu-button--green"><i data-feather="triangle"></i>Утверждено</button></li>
        <li class="menu-item"><button class="menu-button menu-button--black menu-button--checked"><i data-feather="circle"></i>Без статуса<i data-feather="check"></i></button></li>
      </ul>
      <!-- закончилось вложенное меню -->
    </li>
    <!-- обычные пункты меню -->
    <li class="menu-item"><button class="menu-button"><i data-feather="link"></i>Копировать ссылку</button></li>
    <li class="menu-item"><button class="menu-button"><i data-feather="folder-plus"></i>Переместить</button></li>
    <li class="menu-item"><button class="menu-button"><i data-feather="copy"></i>Скопировать</button></li>
    <li class="menu-item"><button class="menu-button"><i data-feather="lock"></i>Защитить</button></li>
    <li class="menu-item"><button class="menu-button"><i data-feather="download"></i>Загрузить</button></li>
  </ul>
  <!-- третий раздел -->
  <ul class="menu-list">
    <li class="menu-item"><button class="menu-button menu-button--delete"><i data-feather="trash-2"></i>Удалить</button></li>
  </ul>
</div>

<!-- подключаем jQuery -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<!-- подключаем иконки-->
<script src='https://unpkg.com/feather-icons@4.29.0/dist/feather.min.js'></script>

<!-- и подключаем наш скрипт -->
<script  src="script.js"></script>
Улучшаем контекстное меню: делаем стильно и красиво
У нас есть все пункты меню, но на контекстное меню это совсем не похоже. Исправим это с помощью стилей

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

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

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

/* для всех элементов и псевдоэлементов  делаем так, */
/* чтобы у них задавались размеры не их контента, а блока, в котором этот контент */
*,
*:after,
*:before {
  box-sizing: border-box;
}

/* блок переменных с цветами для всей страницы */
:root {
  /* фон */
  --color-bg-primary: #d0d6df;
  /* фон выбранного пункта меню */
  --color-bg-primary-offset: #f1f3f7;
  /* цвет фона меню */
  --color-bg-secondary: #fff;
  /* текст */
  --color-text-primary: #3a3c42;
  /* цвет иконок по умолчанию */
  --color-text-primary-offset: #898c94;
  /* цвета для статусов во вложенном меню */
  --color-orange: #dc9960;
  --color-green: #1eb8b1;
  --color-purple: #657cc4;
  /* чёрный цвет совпадает с цветом текста */
  --color-black: var(--color-text-primary);
  /* красный — нужен для пункта «Удалить» */
  --color-red: #d92027;
}

/* настройки для всей страницы */
body {
  /* используем новый шрифр */
  font-family: "Inter", sans-serif;
  /* устанавливаем цвета на странице */
  background-color: var(--color-bg-primary);
  color: var(--color-text-primary);
}
Улучшаем контекстное меню: делаем стильно и красиво
Теперь элементы меню лучше заметны на странице, но до идеала пока далеко

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

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

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

/* общие настройки для всего меню */
.menu {
  /* включаем абсолютное позиционирование */
  position: absolute;
  /* говорим, что содержимое этого блока будет в контейнерах */
  display: flex;
  flex-direction: column;
  /* устанавливаем цвет фона */
  background-color: var(--color-bg-secondary);
  /* добавляем скругление */
  border-radius: 10px;
  /* и отбрасываем тень */
  box-shadow: 0 10px 20px rgba(64, 64, 64, 0.15);
}

/* настройки для каждого раздела меню */
.menu-list {
  /* убираем внешние отступы */
  margin: 0;
  /* каждый элемент будет находиться в своём блоке */
  display: block;
  /* ширина будет зависеть от текста внутри блока */
  width: 100%;
  /* добавляем внутренние отступы */
  padding: 8px;
}

/* настройки для линии-разделителя в меню */
.menu-list + .menu-list {
  /* рисуем верхнюю границу на стыке двух разделов */
  border-top: 1px solid #ddd;
}
Улучшаем контекстное меню: делаем стильно и красиво
Стало немного аккуратнее, но работы ещё много

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

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

/* настройки вложенного меню */
.menu-sub-list {
  /* скрываем его на старте */
  display: none;
  /* добавляем внутренние отступы */
  padding: 8px;
  /* устанавливаем цвет фона */
  background-color: var(--color-bg-secondary);
  /* добавляем скругление и тень */
  border-radius: 10px;
  box-shadow: 0 10px 20px rgba(64, 64, 64, 0.15);
  /* включаем абсолютное позиционирование */
  position: absolute;
  /* сдвигаем вправо на всю ширину родительского меню */
  left: 100%;
  /* пусть верх вложенного меню совпадает с верхом выбранного пункта */
  top: 0;
  /* виртуально выносим вложенное меню вперёд, чтобы оно накладывалось сверху на основное */
  z-index: 100;
  /* ширина меню будет зависеть от текста внутри */
  width: 100%;
  /* блоки с содержимым будут располагаться друг под другом */
  flex-direction: column;
}
/* при наведении мышки на элемент с вложенным меню — показываем вложенное меню */
.menu-button:hover + .menu-sub-list {
  /* до этого у нас было display:none; */
  display: flex;
}

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

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

/* настройки для каждого элемента в меню */
.menu-item {
  /* включаем абсолютное позиционирование */
  position: relative;
}

/* настройки кнопок */
.menu-button {
  /* наследуем шрифт из страницы */
  font: inherit;
  /* убираем границы кнопки */
  border: 0;
  /* добавляем внутренние отступы снизу и сверху */
  padding: 8px 8px;
  /* делаем отступ справа */
  padding-right: 36px;
  /* ширина кнопки будет зависеть от текста внутри */
  width: 100%;
  /* добавляем скругление */
  border-radius: 8px;
  /* выравниваем текст по левому краю */
  text-align: left;
  /* оборачиваем всё в контейнеры */
  display: flex;
  align-items: center;
  position: relative;
  /* цвет фона */
  background-color: var(--color-bg-secondary);
}

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

/* настройки иконок */
.menu-button svg {
  /* делаем иконки нужного размера */
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  /* добавляем отступ справа */
  margin-right: 10px;
  /* рисуем иконку бледно-серым цветом */
  stroke: var(--color-text-primary-offset);
}

/* те иконки, которые стоят после текста (вторые в списке элементов), сдвигаем к правому краю */
.menu-button svg:nth-of-type(2) {
  margin-right: 0;
  position: absolute;
  right: 8px;
}
Улучшаем контекстное меню: делаем стильно и красиво
Намного лучше

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

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

/* что будет при наведении мышки на кнопку */
.menu-button:hover {
  /* меняем цвет фона */
  background-color: var(--color-bg-primary-offset);
}

/* что будет при наведении мышки на кнопку во вложенном меню */
.menu-sub-list:hover {
  /* меняем стиль отображения, чтобы изменился цвет фона */
  display: flex;
}

/* как отреагирует иконка при наведении мышки */
.menu-button:hover svg {
  /* делаем её того же цвета, что и основной текст */
  stroke: var(--color-text-primary);
}



/* подсвечиваем красным пункт «Удалить» при наведении мышки */
.menu-button--delete:hover {
  color: var(--color-red);
}
/* и то же самое делаем с иконкой */
.menu-button--delete:hover svg:first-of-type {
  stroke: var(--color-red);
}

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

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

/* раскрашиваем иконки во вложенном меню */
.menu-button--orange svg:first-of-type {
  stroke: var(--color-orange);
}
.menu-button--green svg:first-of-type {
  stroke: var(--color-green);
}
.menu-button--purple svg:first-of-type {
  stroke: var(--color-purple);
}
.menu-button--black svg:first-of-type {
  stroke: var(--color-black);
}

/* и раскрашиваем галочку во вложенном меню */
.menu-button--checked svg:nth-of-type(2) {
  stroke: var(--color-purple);
}

Пишем скрипт

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

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

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

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

// скрываем контекстное меню
$("div.menu").hide();

// прикрепляем обработчик контекстного меню к элементу с классом "menu"
$(document).bind("contextmenu", function(event) {
		// отменяем действие браузера по умолчанию
    event.preventDefault();
    // показываем наше меню
    $("div.menu")
        .show()
        // привязываем координаты левого верхнего угла к координатам мыши
        .css({top: event.pageY + 15, left: event.pageX + 10});
});

// обработчик клика на странице
// если кликнуть мимо меню — оно исчезнет
$(document).click(function() {
	// смотрим, курсор сейчас находится на меню или нет
	// если на меню — он точно над каким-то элементом и этот элемент сейчас имеет псевдокласс hover
  isHovered = $("div.menu").is(":hover");
  // если курсор ни над одним элементом меню
  if (isHovered == false){
  	// скрываем меню
    $("div.menu").fadeOut("fast");
  }
});

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

<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Стильное контекстное меню</title>
  <!-- подключаем новый шрифт -->
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
  <!-- подключаем нормализатор CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">

  <!-- подключаем свои стили -->
  <link rel="stylesheet" href="style.css">

</head>
<body>
  <!-- всё меню будет в этом блоке -->
  <div class="menu">
    <!-- первый раздел в меню -->
    <ul class="menu-list">
      <!-- список с элементами меню -->
      <li class="menu-item">
        <!-- каждый пункт меню — это кнопка -->
        <button class="menu-button">
          <!-- иконка -->
          <i data-feather="corner-up-right"></i>
            <!-- название пункта меню -->
            Поделиться
        </button>
      </li>
      <!-- начался новый пункт меню -->
      <li class="menu-item"><button class="menu-button"><i data-feather="edit-2"></i>Переименовать</button></li>
    </ul>

    <!-- второй раздел -->
    <ul class="menu-list">
      <li class="menu-item"><button class="menu-button menu-button--black"><i data-feather="circle"></i>Статус<i data-feather="chevron-right"></i></button>
      <!-- делаем вложенное меню -->
        <ul class="menu-sub-list">
          <li class="menu-item"><button class="menu-button menu-button--orange"><i data-feather="square"></i>В работе</button></li>
          <li class="menu-item"><button class="menu-button menu-button--purple"><i data-feather="octagon"></i>На паузе</button></li>
          <li class="menu-item"><button class="menu-button menu-button--green"><i data-feather="triangle"></i>Утверждено</button></li>
          <li class="menu-item"><button class="menu-button menu-button--black menu-button--checked"><i data-feather="circle"></i>Без статуса<i data-feather="check"></i></button></li>
        </ul>
        <!-- закончилось вложенное меню -->
      </li>
      <!-- обычные пункты меню -->
      <li class="menu-item"><button class="menu-button"><i data-feather="link"></i>Копировать ссылку</button></li>
      <li class="menu-item"><button class="menu-button"><i data-feather="folder-plus"></i>Переместить</button></li>
      <li class="menu-item"><button class="menu-button"><i data-feather="copy"></i>Скопировать</button></li>
      <li class="menu-item"><button class="menu-button"><i data-feather="lock"></i>Защитить</button></li>
      <li class="menu-item"><button class="menu-button"><i data-feather="download"></i>Загрузить</button></li>
    </ul>
    <!-- третий раздел -->
    <ul class="menu-list">
      <li class="menu-item"><button class="menu-button menu-button--delete"><i data-feather="trash-2"></i>Удалить</button></li>
    </ul>
  </div>

  <!-- подключаем jQuery -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
  <!-- подключаем иконки-->
  <script src='https://unpkg.com/feather-icons@4.29.0/dist/feather.min.js'></script>

  <!-- и подключаем наш скрипт -->
  <script  src="script.js"></script>



</body>
</html>

/* для всех элементов и псевдоэлементов  делаем так, */
/* чтобы у них задавались размеры не их контента, а блока, в котором этот контент */
*,
*:after,
*:before {
  box-sizing: border-box;
}

/* блок переменных с цветами для всей страницы */
:root {
  /* фон */
  --color-bg-primary: #d0d6df;
  /* фон выбранного пункта меню */
  --color-bg-primary-offset: #f1f3f7;
  /* цвет фона меню */
  --color-bg-secondary: #fff;
  /* текст */
  --color-text-primary: #3a3c42;
  /* цвет иконок по умолчанию */
  --color-text-primary-offset: #898c94;
  /* цвета для статусов во вложенном меню */
  --color-orange: #dc9960;
  --color-green: #1eb8b1;
  --color-purple: #657cc4;
  /* чёрный цвет совпадает с цветом текста */
  --color-black: var(--color-text-primary);
  /* красный — нужен для пункта «Удалить» */
  --color-red: #d92027;
}

/* настройки для всей страницы */
body {
  /* используем новый шрифр */
  font-family: "Inter", sans-serif;
  /* устанавливаем цвета на странице */
  background-color: var(--color-bg-primary);
  color: var(--color-text-primary);
}

/* общие настройки для всего меню */
.menu {
  /* включаем абсолютное позиционирование */
  position: absolute;
  /* говорим, что содержимое этого блока будет в контейнерах */
  display: flex;
  flex-direction: column;
  /* устанавливаем цвет фона */
  background-color: var(--color-bg-secondary);
  /* добавляем скругление */
  border-radius: 10px;
  /* и отбрасываем тень */
  box-shadow: 0 10px 20px rgba(64, 64, 64, 0.15);
}

/* настройки для каждого раздела меню */
.menu-list {
  /* убираем внешние отступы */
  margin: 0;
  /* каждый элемент будет находиться в своём блоке */
  display: block;
  /* ширина будет зависеть от текста внутри блока */
  width: 100%;
  /* добавляем внутренние отступы */
  padding: 8px;
}

/* настройки для линии-разделителя в меню */
.menu-list + .menu-list {
  /* рисуем верхнюю границу на стыке двух разделов */
  border-top: 1px solid #ddd;
}

/* настройки вложенного меню */
.menu-sub-list {
  /* скрываем его на старте */
  display: none;
  /* добавляем внутренние отступы */
  padding: 8px;
  /* устанавливаем цвет фона */
  background-color: var(--color-bg-secondary);
  /* добавляем скругление и тень */
  border-radius: 10px;
  box-shadow: 0 10px 20px rgba(64, 64, 64, 0.15);
  /* включаем абсолютное позиционирование */
  position: absolute;
  /* сдвигаем вправо на всю ширину родительского меню */
  left: 100%;
  /* пусть верх вложенного меню совпадает с верхом выбранного пункта */
  top: 0;
  /* виртуально выносим вложенное меню вперёд, чтобы оно накладывалось сверху на основное */
  z-index: 100;
  /* ширина меню будет зависеть от текста внутри */
  width: 100%;
  /* блоки с содержимым будут располагаться друг под другом */
  flex-direction: column;
}


/* при наведении мышки на элемент с вложенным меню — показываем вложенное меню */
.menu-button:hover + .menu-sub-list {
  /* до этого у нас было display:none; */
  display: flex;
}

/* настройки для каждого элемента в меню */
.menu-item {
  /* включаем абсолютное позиционирование */
  position: relative;
}

/* настройки кнопок */
.menu-button {
  /* наследуем шрифт из страницы */
  font: inherit;
  /* убираем границы кнопки */
  border: 0;
  /* добавляем внутренние отступы снизу и сверху */
  padding: 8px 8px;
  /* делаем отступ справа */
  padding-right: 36px;
  /* ширина кнопки будет зависеть от текста внутри */
  width: 100%;
  /* добавляем скругление */
  border-radius: 8px;
  /* выравниваем текст по левому краю */
  text-align: left;
  /* оборачиваем всё в контейнеры */
  display: flex;
  align-items: center;
  position: relative;
  /* цвет фона */
  background-color: var(--color-bg-secondary);
}

/* настройки иконок */
.menu-button svg {
  /* делаем иконки нужного размера */
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  /* добавляем отступ справа */
  margin-right: 10px;
  /* рисуем иконку бледно-серым цветом */
  stroke: var(--color-text-primary-offset);
}

/* те иконки, которые стоят после текста (вторые в списке элементов), сдвигаем к правому краю */
.menu-button svg:nth-of-type(2) {
  margin-right: 0;
  position: absolute;
  right: 8px;
}

/* что будет при наведении мышки на кнопку */
.menu-button:hover {
  /* меняем цвет фона */
  background-color: var(--color-bg-primary-offset);
}

/* что будет при наведении мышки на кнопку во вложенном меню */
.menu-sub-list:hover {
  /* меняем стиль отображения, чтобы изменился цвет фона */
  display: flex;
}

/* как отреагирует иконка при наведении мышки */
.menu-button:hover svg {
  /* делаем её того же цвета, что и основной текст */
  stroke: var(--color-text-primary);
}



/* подсвечиваем красным пункт «Удалить» при наведении мышки */
.menu-button--delete:hover {
  color: var(--color-red);
}
/* и то же самое делаем с иконкой */
.menu-button--delete:hover svg:first-of-type {
  stroke: var(--color-red);
}

/* раскрашиваем иконки во вложенном меню */
.menu-button--orange svg:first-of-type {
  stroke: var(--color-orange);
}
.menu-button--green svg:first-of-type {
  stroke: var(--color-green);
}
.menu-button--purple svg:first-of-type {
  stroke: var(--color-purple);
}
.menu-button--black svg:first-of-type {
  stroke: var(--color-black);
}

/* и раскрашиваем галочку во вложенном меню */
.menu-button--checked svg:nth-of-type(2) {
  stroke: var(--color-purple);
}

// рисуем стильные иконки
feather.replace();
// скрываем контекстное меню
$("div.menu").hide();

// прикрепляем обработчик контекстного меню к элементу с классом "menu"
$(document).bind("contextmenu", function(event) {
		// отменяем действие браузера по умолчанию
    event.preventDefault();
    // показываем наше меню
    $("div.menu")
        .show()
        // привязываем координаты левого верхнего угла к координатам мыши
        .css({top: event.pageY + 15, left: event.pageX + 10});
});

// обработчик клика на странице
// если кликнуть мимо меню — оно исчезнет
$(document).click(function() {
	// смотрим, курсор сейчас находится на меню или нет
	// если на меню — он точно над каким-то элементом и этот элемент сейчас имеет псевдокласс hover
  isHovered = $("div.menu").is(":hover");
  // если курсор ни над одним элементом меню
  if (isHovered == false){
  	// скрываем меню
    $("div.menu").fadeOut("fast");
  }
});

Текст:

Михаил Полянин

Редактор:

Максим Ильяхов

Художник:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Мария Дронова

Соцсети:

Виталий Вебер

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
Программируем скринсейвер для Илона
Программируем скринсейвер для Илона

Анимация движения звёзд на JavaScript.

medium
ООП: атрибуты и методы
ООП: атрибуты и методы

Два главных слова любого программиста в ООП. Знай их, люби их, говори правильно.

easy
Конец ретроградному Меркурию! Пишем собственный гороскоп на Python

Наш гороскоп точен и прост! Сбросим иго астрологов!

medium
Как сделать таймер
Создаём собственный таймер-напоминалку

Таймеров и трекеров полно, но мы сделаем такой, какой нужен именно вам. Это легко.

medium
Как добавить плавающий блок на страницу
Как добавить плавающий блок на страницу

Иногда это и правда нужно.

easy
Адаптируем статью под время суток
Адаптируем статью под время суток

Простая игрушка на JS.

easy
Текстовый дождь, как в «Матрице»
Текстовый дождь, как в «Матрице»

Приятная кодовая безделушка.

medium
Делаем игру Quatro
Делаем игру Quatro

Интеллектуальная игра для двоих

hard
Что означает ошибка ReferenceError: Invalid left-hand side in assignment
Что означает ошибка ReferenceError: Invalid left-hand side in assignment

Скорее всего, вы используете оператор присваивания вместо сравнения.

easy
Uncaught TypeError: Cannot read property — что это означает
Uncaught TypeError: Cannot read property — что это означает

Нельзя прочитать то, чего нет.

medium
medium