От автора: в этой статье мы расскажем о простом, но очень эффективном методе создания off canvas меню с помощью HTML, CSS и JavaScript.
Чтобы получить общее представление о том, что мы будем создавать, взгляните на демо-версию CodePen, посвящённую этой теме (для ещё лучшего понимание изучите полную версию).
Примечание: В этом руководстве внимание не будет сосредоточено на том, как сделать скрытое меню доступным или адаптивным, так как это уже следующие шаги.
Начнём с разметки
Разметка состоит из двух элементов обёртки:
элемент.top-banner
элемент.top-nav
А вот HTML код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<section class="top-banner"> <div class="top-banner-overlay"> <!-- content here --> </div> </section> <nav class="top-nav"> <div class="menu-wrapper"> <!-- content here --> </div> <div class="fixed-menu"> <!-- content here --> </div> </nav> |
Теперь нам нужен CSS
Когда разметка уже готова, давайте рассмотрим самые важные стили, требующиеся для такого меню.
Примечание: Для читаемости CSS кода, он не оптимизирован, вы заметите в нём повторяющиеся свойства, которые сможете убрать из собственной версии.
Добавление стилей для элемента top-banner
Элемент.top-banner выглядит следующим образом:
Что мы делаем с помощью стилей:
Задаём его ширину равной ширине окна минус ширина элемента.menu-wrapper.
Задаём его высоту равной высоте окна.
Определяем его как flex-контейнер. Это заставит его верхний слой растягиваться на всю высоту родительного элемента.
Используем flexbox, чтобы разместить содержимое верхнего слоя вертикально по центру.
Для этого нам понадобятся следующие стили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
.top-banner { display: flex; width: calc(100% - 150px); height: 100vh; transform: translateX(150px); background: url(IMAGE_PATH) no-repeat center / fixed; } .top-banner-overlay { display: flex; flex-direction: column; justify-content: center; width: 350px; padding: 20px; transition: transform .7s; color: white; background: rgba(0, 0, 0, .7); } |
Добавляем стили для элемента top-nav
Элемент.top-nav выглядит следующим образом:
Далее делаем вот что:
Указываем прямые дочерние элементы как фиксировано позиционированные элементы, которые растягиваются на всю высоту окна.
Используем flexbox, чтобы вертикально выровнять элемент.fixed-menu.
Прячем по умолчанию элемент.menu-wrapper. Для этого мы не задаём ему такое значение свойства как display: none. Фактически, мы используем функциюtranslate(), чтобы передвинуть его на 200px влево. Примите во внимание, что ширина элемента составляет 350px, так что его часть всё ещё находится в окне просмотра. Однако, его не видно, потому что элемент размещён под элементом.fixed-menu.
Прячем список меню.
Вот соответствующие CSS стили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
.top-nav .menu-wrapper { position: fixed; top: 0; left: 0; bottom: 0; width: 350px; padding: 20px; transform: translateX(-200px); transition: transform .7s; background: #B1FFE5; } .top-nav .menu-wrapper .menu { opacity: 0; transition: opacity .4s; } .top-nav .fixed-menu { position: fixed; top: 0; left: 0; bottom: 0; display: flex; flex-direction: column; width: 150px; padding: 20px; background: aquamarine; } |
Пришло время JavaScript
На этом этапе мы используем немного простейшего JavaScript-кода, чтобы изменить состояние скрытого меню.
Итак, какие наши следующие действия:
Когда нажимается кнопка .menu-open, меню должно появляться с красивым эффектом всплывания и смещать верхний слой вправо. К этому мы может добавить ещё много интересного. В нашем примере мы добавили тень псевдо-элементу верхнего слоя ::before и выделили появление списка меню с помощью эффекта плавности.
Когда нажимается кнопка.menu-close, меню должно исчезать с впечатляющим эффектом ускользания, а верхний слой должен возвращаться обратно влево.
Ниже приведён JavaScript код, который выполняет эти инструкции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
const menuOpen = document.querySelector(".top-nav .menu-open"); const menuClose = document.querySelector(".top-nav .menu-close"); const menuWrapper = document.querySelector(".top-nav .menu-wrapper"); const topBannerOverlay = document.querySelector(".top-banner-overlay"); function toggleMenu() { menuOpen.addEventListener("click", () => { menuWrapper.classList.add("is-opened"); topBannerOverlay.classList.add("is-moved"); }); menuClose.addEventListener("click", () => { menuWrapper.classList.remove("is-opened"); topBannerOverlay.classList.remove("is-moved"); }); } toggleMenu(); |
А здесь приведены соответствующие CSS стили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
.top-banner-overlay.is-moved { transform: translateX(350px); } .top-banner-overlay.is-moved::before { content: ''; position: absolute; top: 0; bottom: 0; right: 100%; width: 20px; box-shadow: 0 0 10px black; } .top-nav .menu-wrapper.is-opened { transform: translateX(150px); } .top-nav .menu-wrapper.is-opened .menu { opacity: 1; transition-delay: .6s; } |
Поддержка браузерами
Эта демо-версия будет работать только в браузерах для стационарных компьютеров. Для мобильных устройств будут нужны другие макеты страницы, но это выходит за пределы этого руководства. Как обычно, мы используем Babel для компиляции ES6 кода в ES5.
Единственная маленькая проблема, с которой я столкнулся по время тестирования, это изменение отображения текста, которое случилось во время анимации верхнего слоя. Хотя я пробовал различные подходы, которые нашёл в разных потоках Stack Overflow, но так и не смог найти простое решение для всех операционных систем и браузеров. Так что учтите, вы можете заметить небольшие проблемы с изменением шрифта во время анимации верхнего слоя.
Заключение
Вот и всё, ребята! Нам удалось создать off-canvas меню с помощью относительно простого кода. Я надеюсь, вы довольны конечным результатом и будете вдохновляться им для создание ещё более эффектных off-canvas меню. И, конечно же, если вы создадите такое меню, не забудьте поделиться этим с нами!
Автор: George Martsoukos
Источник: //webdesign.tutsplus.com/
Редакция: Команда webformyself.