image

Коротко о меню


  • 99% меню HTML5 + CSS3, 1% JavaScript (закрытие открытой категории по клику).
  • На мобильных устройствах «горизонтальное» меню становится «аккордеон-меню».
  • В первичном состоянии показаны 10 основных пунктов меню из 33, остальные пункты появляются при нажатии на 11-ый (крайне правый пункт) «Ещё...».
  • «Время загрузки для взаимодействия» страницы категории с меню и товарами на компьютере 1 секунда, на мобильных 5,2 секунд (по данным developers.google.com).
  • «Время загрузки первого контента» страницы категории с меню и товарами на компьютере 0,3 секунды, на мобильных 1 секунда (по данным developers.google.com).
  • Категории меню открываются и закрываются по нажатию, после открытия символ "+" меняется на "-".
  • При открытии других пунктов меню, открытые ранее закрываются.
  • Подпункты-категорий и подпункты-подпунктов-категорий меню на desktop помещаются в область просмотра без полосы прокруток.

Требования к меню


  • Открытие меню по нажатию… Про меню с открытием при наведении: при открытие страницы 99% людей пересечет мышкой меню, что вызовет его незапланированное появление закрыв видимую часть экрана тем самым расстроив посетителя. Решить можно включив задержку при наведении (чтоб не открывалось сразу), но тогда меню «тормозное» становится.
  • Простое меню для возможной дальнейшей корректировки сотрудниками магазина после инструктажа.
  • Меню должно быть адаптивное, страница с меню проходить полную валидацию css3 html5. Скорость загрузки страницы должна оставаться быстрой.

Полную версию меню можно посмотреть codepen.io/andrej-sh/pen/eYOrNEZ

Начало HTML кода


Часть кода

Пояснение к коду JavaScript


Планировал обойтись без JavaScript, но реализация закрытия открытого меню при повторном нажатии на CSS мне не представилась реализуемой для radio + checkbox. А код простой и понятный и даже при его случайном удалении не способен сделать сайт не рабочим (при тестировании меню с jQuery сайт не работал 5 минут из-за того, что сперва подключил скрипт удаленно и в ссылке был http вместо https).

<script>
function clickRadio(el) {
  var siblings = document.querySelectorAll("input[type='radio'][name='" + el.name + "']");
  for (var i = 0; i < siblings.length; i++) {
    if (siblings[i] != el)
      siblings[i].oldChecked = false;
  }
  if (el.oldChecked)
    el.checked = false;
  el.oldChecked = el.checked;
}</script>

Аналогичное меню с использованием jQuery


Первая версия меню была на jQuery, реализована через input «checkbox». Еще через скрипт было настроено появление символов "+ -" при открытии-скрытии меню. По функционалу и внешнему виду абсолютно такое же как и про меню описанному ранее. Но! скорость загрузки была заметно хуже. Например «Максимальная потенциальная задержка FID» становится больше на 1 секунду. «Время загрузки для взаимодействия» больше на 0,6-0,8 секунды. «Время загрузки первого контента» на 0,3-0,4 секунды. Скрипты грузятся на 0,5 секунды дольше.

Изображения с сервисов проверки скорости загрузок


Для компьютеров

Для мобильных

Lighthouse

Комментарии (14)


  1. Carduelis
    11.09.2019 12:13

    Меню не закрывается при клике "вне меню". А это довольно-таки, привычная вещь для пользователей, и является неотъемленной частью UX таких меню.


    А вообще, на продакшене использовать "только css"-меню довольно затруднительно. Слишком много возможных "хотелок" приведут к переписыванию на javascript.


    А если замените дефис на минус, выглядеть будет приятнее. Кстати, Accessibility тоже надо доводить до 100%


    1. Andrey_Shatilo Автор
      11.09.2019 12:48

      Меню не закрывается при клике «вне меню».А это довольно-таки, привычная вещь для пользователей,..
      Полностью согласен, в планах.
      А если замените дефис на минус
      Спасибо за решение!
      Accessibility не 100% так как загрузка каталога товаров через «яндекс поиск для им» который через iframe работает, а другой вид загрузки через json еще не настроен.


  1. NoRegrets
    11.09.2019 16:44

    Меню — прям огонь! Шутка, конечно же. Это какой-то привет из 2000х.
    Минусы — слишком много текста, нужно слишком много прочесть, пока выберешь нужное, нужно сделать несколько кликов и не промахнуться. Кнопку «еще+» нажмет один процент, остальные просто не найдут то, что искали.
    Лучше сделать так как сделано на али, амазоне, озоне. Для того чтобы войти в нужный раздел, порой нужно пройти пару страниц. Но чисто психологически это комфортнее, чем лазить по представленной в статье менюшке, поэтому такие менюшки и померли. Такая менюшка будет работать только если человек зашел на сайт с ясным желанием, что ему нужно прямо сейчас и он знает где искать. Т.е. для какой-нибудь внутренней erp/crm будет нормально, для интернет-магазина — нет. Все сказанное ИМХО.


  1. Alexufo
    11.09.2019 17:53

    jQuery какой версии?


    1. Andrey_Shatilo Автор
      12.09.2019 06:38

      jQuery v1.6.4


      1. Alexufo
        12.09.2019 09:18

        нууу… 2011 года релиз. Там еще ie7 поддерживется, конечно это старая и медленная версия.


        1. Andrey_Shatilo Автор
          12.09.2019 09:29

          Скачал jquery-3.4.1.min.js замеряю скорость…
          Максимальная потенциальная задержка FID теперь почти не отличается от версии меню без jquery… Разница у «Время загрузки первого контента» и «Время загрузки для взаимодействия» стали меньше…
          Спасибо что обратили внимание на версию jquery


          1. Alexufo
            12.09.2019 12:49

            можно еще jQuery slim с вырезанным ajax и эффектами, если они не используются на сайте


  1. ilya-ivanov
    11.09.2019 21:57

    1. Меню такого объема лучше делать вертикальным: нет лимита по длине, избавляет от «Ещё...», можно интуитивно сортировать и фильтровать (расположив инпут/панель фильтров над меню). Плюс это позволит выполнить пункт 2.

    2. Минимальные габариты кликабельной плашки желательно делать такими, чтобы туда влезал палец (48x48 px и более). Это очень сильно снижает количество мискликов и, след-но, отказов. На десктопе тоже! Не забывайте, что не все люди обладают точной моторикой и зрением, а с возрастом всё это проседает. Чем старше аудитория, тем критичнее размеры областей клика.

    3. В идеале меню должно управляться и табуляцией. Включая перемещение по подпунктам с клавиатуры. У нас все забивают, но в зарубежных проектах это бывает базовым требованием. Там больше доля ридеров и всяких гаджетов, поэтому все помешаны на accessibility. В разметке желательно следить за семантикой (nav), в некоторых случаях внедрятьARIA-roles и т.д.

    4. Нежелательно делать «выворотку» (светлый текст на темном фоне) для светлых тем. Контраст цветов фона и текста лучше держать повыше (примерно как у вас в выделенных пунктах).

    5. Минимальный размер шрифта сейчас желательно делать минимум 16px для десктопа, причем брать гротески а не антиквы. Для сжатых и мелких гарнитур (Pt Sans и др) размер шрифта надо брать даже чуть больше — ~18 или выше.

    6. В меню такой вложенности желательно показывать кол-во дочерних элементов и товаров, особенно если вы требуете полный клик, чтобы показать подуровень. Иначе у вас будут ситуации, когда человек делает 3-6 кликов, а в итоге оказывается в пустой или почти пустой подподкатегории, где нечего выбирать.

    7. Желательно обрабатывать не только состояние hover, но и active и pressed/selected. Т.е. меню должно чем-то реагировать на нажатие и различать текущую цепочку навигации (на какой странице находимся) от простой подсветки пунктов при их просмотре (какой пункт меню под мышкой).

    8. Не очень удачно делать два ряда горизонтальных меню друг под другом. См п.1.

    9. Про скрытие меню по клику на оверлей (вне меню) уже написали выше. В идеале ещё по клавише Esc (и «назад» на телефонах)

    10. В идеале (без прямолинейного сео) вложенность основного меню надо уменьшать до 1-2 уровней. А более глубокую рубиркацию показывать после перехода внутрь. Точкой входа в магазин почти всегда становится не главная, а внутренняя страница. Т.е. человеку, который пришел по запросу «Сантехника», выгоднее на первом же уровне (без кликов) показать Унитазы и Раковины, а не Инструмент и Краску. Верхний уровень на внутряках как раз лучше показывать по прямому запросу, то есть по клику на общую кнопку типа «Все рубрики», «Полный каталог» и т.п.

    P.S. 36k — это не настолько много) Норма для большого тематического магазина. А ведь есть ещё гипермаркеты)

    Успехов!


    1. Andrey_Shatilo Автор
      12.09.2019 07:11

      Спасибо за подробные идеи!
      1. Пробовал, на компьютерах очень много места занимает и далеко листать вниз. Даже если 2х уровневое делать то получается до 58 строчек 33+25 подкатегорий у нажатого пункта. Такое меню не устроило руководство.
      2. Я бы с радостью крупней меню делал, но тогда будет полоса прокрутки, а при ней люди часто нажимают рядом с меню (а в этой ситуации меню должно закрываться Пункт 9)
      3-5 согласен
      6. Возможна ситуация: человек подумает что это не количество подпунктов, а количество товаров и тогда даже не нажмет на пункт меню. А подписывать что это количество категорий грамозко. У конечных категорий вполне можно добавить количество товаров в категории.
      7-10. согласен, это очень нужно
      P.S 36к это и есть гипермаркет. У Леруа Мерлен 30-44к в зависимости от города. У нас уже 37к


  1. vadimm0s
    12.09.2019 06:38

    В целом интересное решение.
    Думаю не повредило бы еще заблокировать выделение текста внутри пунктов меню.


  1. DimNS
    12.09.2019 09:41

    Нуу даже не знаю, вроде бы уже всё давно придумано, вон теми же ситилинк и технопоинт\днс


    1. Alexufo
      12.09.2019 16:17

      nix еще держится)


  1. Zezst
    12.09.2019 10:46

    Открытие меню по нажатию… Про меню с открытием при наведении: при открытие страницы 99% людей пересечет мышкой меню, что вызовет его незапланированное появление закрыв видимую часть экрана тем самым расстроив посетителя. Решить можно включив задержку при наведении (чтоб не открывалось сразу), но тогда меню «тормозное» становится.

    Я бы все же сделал открытие по hover`у, а затем привел к нужному поведению через js. Тогда и проблем с закрытием меню при клике мимо меньше было бы. Плюс полностью рабочее меню да при условии выключенного js (хотя кто сейчас выключает js, кроме меня, не знаю)