Адаптивное выпадающее мега меню на CSS

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

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

Каждый столбец внутри выпадающего меню представляет собой элемент списка, содержащий внутри заголовок (опционально) и вложенное меню.

Рис. 1. Контейнер для колонок мега меню
Рис. 2. Вложенное меню

Высота каждой колонки может разной и если вы добавите фон или границы для вложенного меню, то разница в высоте будет заметна. Поэтому, чтобы решить эту проблему, подключим Jquery плагин matchHeight.

Необходимые файлы раздела head

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.matchHeight/0.7.0/jquery.matchHeight-min.js"></script>

HTML разметка

<nav class="container">
  <ul class="top-menu">
    <li><a href="">Главная</a></li>
    <li class="dropdown-standart"><a href="" class="dropdown">Страницы</a>
      <ul class="submenu-standart">
        <li><a href="">Элемент списка</a></li>
        <li><a href="">Элемент списка</a></li>
        <li><a href="">Элемент списка</a></li>
        <li><a href="">Элемент списка</a></li>
        <li><a href="">Элемент списка</a></li>
        <li><a href="">Элемент списка</a></li>
      </ul>
    </li>
    <li><a href="" class="dropdown">Магазин</a>
      <ul class="submenu">
        <li><h3>Колонка 1</h3>
          <ul>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
          </ul>
        </li>
        <li><h3>Колонка 2</h3>
          <ul>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
            <li><a href="">Элемент списка</a></li>
          </ul>
        </li>
        <li>
          <ul>
            <li>
              <a href="" class="link-image">
              <img src="https://html5book.ru/wp-content/uploads/2017/01/white-lady.jpg">
              </a>
            </li>
            <li><h3 class="image-header">Заголовок</h3></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="">Портфолио</a></li>
    <li><a href="">Блог</a></li>
  </ul>
</nav>

CSS стили

@import url('https://fonts.googleapis.com/css?family=Playfair+Display|Roboto');
*{box-sizing: border-box;}
body {
  font-family: 'Roboto', sans-serif;
  font-size: 14px;
  margin: 0;
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
a {text-decoration: none;}
.top-menu {
  background: white;
  position: relative;
}
.top-menu:after, 
.submenu:after {
  content: "";
  display: table;
  clear: both;
}
.top-menu > li {
  display: inline-block;
  float: left;
}
.top-menu > li > a {
  display: block;
  padding: 18px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #000;
  transition: .2s linear;
}
.top-menu > li > a:hover {color: #B03062;}
.dropdown:after {
  content: "\f107";
  font-family: FontAwesome;
  margin-left: 4px;
  vertical-align: top;
}
.submenu, 
.submenu-standart {
  border-top: 1px solid #e5e5e5;
  box-shadow: 0 3px 5px 0 rgba(0,0,0,.07);
  background: white;
  padding: 25px 0;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 5;
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0,30px,0);
  transition: .5s ease-out;
  transform-origin: 0% 0%;
}
.submenu {width: 100%;}
.submenu-standart {
  min-width: 200px;
  padding: 10px 0;
}
.dropdown-standart {position: relative;}
.top-menu > li:hover .submenu, 
.top-menu > li:hover .submenu-standart {
  opacity: 1;
  visibility: visible;
  transform: translate3d(0,0,0);
}
.submenu > li {
  float: left;
  width: calc(100% / 3);
  padding: 0 18px;
  border-right: 1px solid #e5e5e5;
}
.submenu-standart li {padding: 0 18px;}
.submenu > li:last-child {border-right: none;}
.submenu img {
  display: block;
  width: 100%;
}
.submenu li a, 
.submenu-standart li a {
  display: block;
  padding: 5px 0;
  color: #666;
  font-size: 13px;
}
.submenu li .link-image {padding: 0;}
.submenu li a:hover {color: #B03062;}
.submenu h3 {
  font-family: 'Playfair Display', serif;
  font-size: 20px;
  font-weight: 400;
  margin: 10px 0;
}
.container {
  max-width: 960px;
  margin: 0 auto;
}
.content {
  margin: 20px auto;
  padding: 0 20px;
}

Добавим адаптивность для мобильных устройств

@media(max-width:768px) {
  .top-menu li {
    width: 100%;
    height: auto!important;
  }
  .top-menu > li {border-bottom: 1px solid #e5e5e5;}
  .top-menu > li > a {padding: 18px}
  .submenu,
  .submenu-standart {
    position: relative;
    display: none;
    box-shadow: none;
    padding: 0;
    background: rgba(0,0,0,.02);
  }
  .submenu-standart {padding: 10px 0;}
  .submenu > li {
    border-right: none;
    border-bottom: 1px solid #e5e5e5;
    padding: 18px;
  }
  .submenu h3 {margin: 0 0 10px}
  .submenu .image-header {margin: 10px 0}
  .submenu li:last-of-type {border-bottom: none}
  .top-menu > li:hover .submenu,
  .top-menu > li:hover .submenu-standart {display: block;}
}

Активация плагина matchHeight

jQuery(document).ready(function($) {
  $('.submenu > li').matchHeight();
});

See the Pen apGgYv by Elena (@html5book) on CodePen.

Эффекты для появления мега меню

В приведённом примере меню появляется, скользя снизу-вверх. Чтобы разнообразить свои проекты, можно воспользоваться одним из следующих эффектов:

1. Поворот из глубины экрана

.submenu {
  border-top: 1px solid #e5e5e5;
  box-shadow: 0 5px 5px 0 rgba(0,0,0,.05);
  background: white;
  padding: 30px 0;
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  z-index: 5;
  opacity: 0;
  visibility: hidden;
  transform: perspective(600px) rotateX(-90deg);
  transform-origin: 0% 0%;
  transition: .4s ease-in;
}
.top-menu > li:hover .submenu {
  opacity: 1;
  visibility: visible;
  transform: perspective(600px) rotateX(0);
}

2. Скольжение сверху-вниз

.submenu {
  border-top: 1px solid #e5e5e5;
  box-shadow: 0 5px 5px 0 rgba(0,0,0,.05);
  background: white;
  padding: 30px 0;
  position: absolute;
  left: 0;
  width: 100%;
  top: -60px;
  opacity: 0;
  z-index: -1;
  transition: .4s cubic-bezier(.6, .04, .98, .335);
}
.top-menu > li:hover .submenu {
  top: 100%;
  opacity: 1;
  z-index: 5;
}

3. Скольжение слева-направо

.submenu {
  border-top: 1px solid #e5e5e5;
  box-shadow: 0 5px 5px 0 rgba(0,0,0,.05);
  background: white;
  padding: 30px 0;
  position: absolute;
  width: 100%;
  top: 100%;
  left: -60px;
  opacity: 0;
  visibility: hidden;
  z-index: 5;
  transition: .4s cubic-bezier(.455, .03, .515, .955);
}
.top-menu > li:hover .submenu {
  left: 0;
  opacity: 1;
  visibility: visible;
}

4. Эффект масштабирования

.submenu {
  border-top: 1px solid #e5e5e5;
  box-shadow: 0 5px 5px 0 rgba(0,0,0,.05);
  background: white;
  padding: 30px 0;
  position: absolute;
  width: 100%;
  top: 100%;
  left: 0;
  opacity: 0;
  z-index: 5;
  transform: scale3d(0,0,0);
  transform-origin: top left;
  transition: .4s cubic-bezier(0.39, 0.575, 0.565, 1);
}
.top-menu > li:hover .submenu {
  left: 0;
  opacity: 1;
  transform: scale3d(1,1,1);
}
  • Создание Сайтов

    Урок конечно замечательный, за что большая благодарность Автору проекта. Но для меня, это только полдела — нужно все это, как-то натянуть на WordPress! Будем упражнять. Еще раз спасибо, за столь ценный урок.

    • Пожалуйста. Для WordPress можно взять плагин, например, https://ru.wordpress.org/plugins/megamenu/.

      • Создание Сайтов

        О-о, это вообще супер! Премного благодарен! Теперь можно экспериментировать и комбинировать.

        • Пожалуйста))

          • Создание Сайтов

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

          • Создание Сайтов

            Есть вот такой код: width: calc(100% / 3); который разбивает меню на 3 колонки. Как в последнюю колонку прописать картинку беграундом через таблицу?

          • Нужно добавить фон в .submenu > li:last-child{background:url(image.img)}

          • Создание Сайтов

            это я пробовал, выводится фон в последнем ссылке второй колонки.
            Вот так делал: .sub-menu:last-child { background-image:url(https://html5book.ru/wp-content/uploads/2017/01/white-lady.jpg); background-repeat:no-repeat;}
            Выводится в первой колонке. Третья колонка вообще проблематичная — меню даже не выводится там.

          • Создание Сайтов

            И почему-то в третью колонку меню не перетекает. Как сделать чтобы оно отображалось больше чем в двух колонках?

          • Очень сложно угадывать причину, не видя живого примера, полноценного, с разметкой и стилями.

          • Создание Сайтов

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

  • Создание Сайтов

    С вариантами что-то запутался. Что заменить в таблице.

    • В данном примере два вида подменю — мега меню .submenu и обычное выпадающее .submenu-standart. Я объединила их стили в одно объявление — это строчки 44 и 66.

      • Создание Сайтов

        Ага, Благодарность.

  • Albert Karimov

    Юзабельное меню для просмотра на ПК, с мобильных же устройств наблюдать все разделы при переходе в каждый раздел или при просмотре статей крайне неудобно. Есть ли возможность вызывать меню по кнопке для мобильных устройств?

    • Есть, постараюсь в ближайшее время дополнить урок.

    • Сделала пример, посмотрите https://codepen.io/html5book/pen/BWroQy.
      Добавляем в разметку кликабельную иконку с помощью

      <label for="mobile-button"><i class="fa fa-bars"></i></label>	
      <input id="mobile-button" type="checkbox">
      • Albert Karimov

        Елена, спасибо! Теперь ваше меню можно в подборки лучших адаптивных решений добавлять!

  • Макс

    подскажите, пожалуйста, есть ли для joomla plugin ?

  • Alex Reg

    Здраствуйте, ваше меню и решение для мобильных устройств очень понравилось. Но столкнулся с проблемой как раз на мобильных устройствах, если по касанию экрана открыть например раздел (Страницы) выпадает список элементов и если я хочу дальше перейти например на раздел (Магазин) опять же касанием экрана то этим действие активируеться одна из ссылок в списке элементов в разделе (Магазин) и пользователь уходит по этой ссылке хотя он должен увидеть просто открытый другой раздел, нет ли какого то просто го решения данной проблемы ? Спасибо.

    • Здравствуйте. Для данного примера добавила .dropdown:hover, .dropdown-standart:hover {pointer-events: none;} и теперь на мобильном нет перехода по верхней ссылке.