Создание мобильного меню на CSS3 и Javascript

Всем привет! В этот статье будет рассмотрено создание мобильного меню с использованием CSS3 и Javascript (без использования jQuery).

Наша задача – создать красивое меню для мобильных устройств, которое будет плавно открываться и закрываться без тормозов. Как правило, у адаптивных сайтов делают кнопку, по нажатию которой меню либо раскрывается, либо выезжает сбоку. Мы будем реализовывать именно второй вариант. Комментарии в коде будут на английском, т.к. проект лежит в репозитории на github.

Шаг 1. Создаем HTML разметку

На данном этапе нам нужно создать два контейнера – один для меню (cool-menu) и второй для всего содержимого страницы (page-wrapper). В содержимом страницы добавим какой-нибудь заголовок и текст, а также кнопку для активации/деактивации меню:

...
<ul id="cool-menu">
  <li><a href="/">Home</a></li>
  <li><a href="/shop">Shop</a></li>
  <li><a href="/about">About Us</a></li>
 </ul>
 
 <div id="page-wrapper">
   <div class="header">
      <h1>Cool Menu</h1>
      <a id="cool-menu-toggle" href="#">Click</a>
   </div>
   <div class="content">
     Lorem ipsum dolor sit amet...
   </div>
 </div>
...

Порядок расположения этих контейнеров неважен, но логичнее что меню находится выше, чем основное содержание страницы.

Шаг 2. Добавляем CSS стили

Теперь нужно задать расположение всех элементов нашей страницы, а также добавить css классы для анимации. Я задал ширину меню 240px, поскольку, на мой взгляд, такая ширина оптимальна для просмотра на устройствах с небольшим экраном. Вы можете легко адаптировать этот код под свои нужды:


html, body {
  margin: 0;
  padding: 0;
  font-family: Helvetica, Arial, sans-serif;
  height: 100%;
}

#page-wrapper {
  position: relative;
  z-index: 20; /* Should be greater than menu z-index */
  padding: 10px 20px;
  background: #fff;
  height: 100%;
}

#page-wrapper h1 {
  margin: 0;
}

#cool-menu-toggle {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 10px;
  border: 1px solid #333;
  border-radius: 3px;
}

#cool-menu {
  display: none;
  height: 100%;
  position: absolute;
  top: 0;
  right: 0;

  width: 190px;
  padding: 15px 25px;
  margin: 0;

  list-style: none;
  background: #333;
  z-index: 10; /* Should be lower than menu z-index */
}

#cool-menu a {
  display: block;
  color: #fff;
  padding: 15px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

Добавьте этот код на страницу. Меню видно не будет, так как для него задано свойство display: none .

На этом шаге некоторые подумали, что теперь можно подключить jQuery и использовать анимацию для того, чтобы двигать меню туда/сюда. Но это будет глючно работать на мобильных устройствах, потому что браузер будет тратить время на пересчёт позиций элементов страницы. К тому же ни к чему подключать библиотеку jQuery, если можно обойтись чистым Javascript: экономия трафика, что немаловажно на мобильных устройствах.

Вместо jQuery анимации будем использовать css свойство translate3d. Благодаря этому, браузер не будет пересчитывать позиции элементов, этой операцией займется видеокарта (GPU). GPU создана для такой работы, поэтому анимация будет происходить быстрее и плавнее, чем при простом переносе элемента.

Чтобы контролировать положение нашего меню, нужно добавить немного кода на Javascript.

Шаг 3. Добавляем логику на Javascript

У разрабатываемого меню может быть 4 положения:

  • Анимации нет, меню скрыто
  • Страница двигается влево, меню открывается
  • Анимации нет, меню открыто
  • Страница двигается вправо, меню закрывается

Мы будем добавлять определенный класс к элементу body, в зависимости от того, в каком положении находится меню:


document.addEventListener('DOMContentLoaded', function(event) {
 
 var onTransitionEnd = function() {
 var body = document.body, page = document.getElementById('page-wrapper');
 
 body.classList.remove('animating');
 body.classList.remove('left');
 body.classList.remove('right');
 
 body.classList.toggle('menu-visible');
 
 page.transitionend = 
 page.webkitTransitionEnd =
 page.otransitionend = 
 page.MSTransitionEnd = null;
 };
 
 // Run if toggle menu button was tapped or clicked
 document.getElementById('cool-menu-toggle').addEventListener('click', function(e) {
 e.preventDefault();
 
 var body = document.body, page = document.getElementById('page-wrapper');

// When the toggle menu link is clicked, animation starts
 body.classList.add('animating');
 
 // Set direction of the animation
 body.classList.add(body.classList.contains('menu-visible') ? 'right' : 'left');
 
 // add event listeners for transition end event
 if (page.addEventListener) {
  page.addEventListener('transitionend', onTransitionEnd, false);
  page.addEventListener('webkitTransitionEnd', onTransitionEnd, false);
  page.addEventListener('otransitionend', onTransitionEnd, false);
  page.addEventListener('MSTransitionEnd', onTransitionEnd, false);
 } else {
  page.attachEvent('transitionend', onTransitionEnd);
  page.attachEvent('webkitTransitionEnd', onTransitionEnd);
  page.attachEvent('otransitionend', onTransitionEnd);
  page.attachEvent('MSTransitionEnd', onTransitionEnd);
 }
 });
});

Что делает этот код?

  1. Анимации нет, меню скрыто – у body нет классов
  2. Страница двигается влево, меню открывается – body добавляются классы animating и left
  3. Анимации нет, меню открыто – body добавляется класс menu-visible
  4. Страница двигается вправо, меню закрывается – body добавляются классы animating и right

На следующем шаге добавим эти css классы, чтобы реализовать анимацию.

Шаг 4. Добавляем анимацию

Добавим в конец нашего файла со стилями несколько новых правил, которые используют css свойство transition3d:


/* Animations */

#page-wrapper, #cool-menu {
  -webkit-backface-visibility: hidden;
  -webkit-perspective: 1000;
}

.animating #cool-menu, .menu-visible #cool-menu {
  display: block;
}

.animating #page-wrapper {
  transition: transform .25s ease-in-out; /* 250ms transition to page */
  -webkit-transition: -webkit-transform .25s ease-in-out;
}

.animating.left #page-wrapper {
  transform: translate3d(-240px, 0, 0 ); /* move page to left */
  -webkit-transform: translate3d(-240px, 0, 0);
}

.animating.right #page-wrapper {
  transform: translate3d(240px, 0, 0); /* move page to right */
  -webkit-transform: translate3d(240px, 0, 0);
}

.menu-visible #page-wrapper {
  right: 240px;
}

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

#cool-menu-toggle {
  display: none;
}
 
@media only screen and (max-width: 768px) {
  #cool-menu-toggle {
    display: block;
  } 
}

Создание мобильного меню – это просто!

На этом наше меню готово! Меню выглядит вот так:

Создание мобильного менюСоздание мобильного меню

Демо можно посмотреть здесь, весь код доступен на github. Создание мобильного меню не так сложно, как казалось ранее. Если остались вопросы, задавайте их в комментариях!

1618