Mobile Menu
This implementation uses classList
which is not fully supported in all browsers (stupid IE). If you need it, you should pull in the the polyfill.
Markup
<div class="SiteContainer">
<!--
We keep our mobile menu as the top most element
to make it easier to keep off canvas
-->
<nav class="Nav Nav--mobile" aria-hidden="true">
<ul id="menu-main-menu" class="menu">
<li id="menu-item-22" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22">
<a href="https://objectiv.co/work/" itemprop="url">Work</a>
</li>
<li id="menu-item-21" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-21">
<a href="https://objectiv.co/services/" itemprop="url">Services</a>
</li>
<li id="menu-item-23" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-23">
<a href="https://objectiv.co/our-story/" itemprop="url">Our Story</a>
</li>
<li id="menu-item-3617" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-3617">
<a href="https://store.objectiv.co" itemprop="url">Plugins</a>
</li>
<li id="menu-item-20" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20">
<a href="https://objectiv.co/blog/" itemprop="url">Blog</a>
</li>
<li id="menu-item-19" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19">
<a href="https://objectiv.co/contact/" itemprop="url">Contact</a>
</li>
</ul>
</nav>
<div class="SiteHeader" role="banner" itemscope itemtype="http://schema.org/WPHeader">
<h1 class="SiteTitle" itemscope itemtype="http://schema.org/Organization">
<a itemprop="url" href="#" rel="home">
<img itemprop="logo" class="Logo" src="https://placehold.it/140x40?text=LOGO" height="42" width="140" alt="">
<!--
Visually hide this text.
WCAG 2.0: “image alt text cannot be the primary text of a link"
-->
<span class="screen-reader-text">Objectiv</span>
</a>
</h1>
<button class="NavToggle" aria-expanded="false">
<div class="NavToggle-icon">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<span class="screen-reader-text">Primary Menu</span>
</button>
</div>
</div>
Styles
CSS
body {
margin: 0;
padding: 0;
}
.screen-reader-text {
clip: rect(1px, 1px, 1px, 1px);
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
}
.SiteContainer {
position: relative;
right: 0;
transition: all 0.5s ease-in-out;
}
.SiteContainer.Nav--is-visible {
right: 300px;
}
.SiteHeader {
align-items: center;
background: #555;
display: flex;
padding: 10px;
}
.SiteTitle {
margin: 0;
}
.Logo {
display: block;
}
.NavToggle {
background: none;
border: none;
color: #fff;
font-size: 18px;
margin-left: auto;
}
.NavToggle-icon {
height: 12px;
position: relative;
transform: rotate(0deg);
transition: all 0.25s ease-in-out;
width: 20px;
}
.NavToggle-icon span {
display: block;
position: absolute;
height: 2px;
width: 100%;
background: #fff;
border-radius: 0;
opacity: 1;
left: 0;
transform: rotate(0deg);
transition: all 0.25s ease-in-out;
}
.NavToggle-icon span:nth-child(1) {
top: 0px;
}
.NavToggle-icon span:nth-child(2),
.NavToggle-icon span:nth-child(3) {
top: 5px;
}
.NavToggle-icon span:nth-child(4) {
top: 10px;
}
.NavToggle.Nav--is-visible .NavToggle-icon span:nth-child(1) {
opacity: 0;
}
.NavToggle.Nav--is-visible .NavToggle-icon span:nth-child(2) {
transform: rotate(45deg);
}
.NavToggle.Nav--is-visible .NavToggle-icon span:nth-child(3) {
transform: rotate(-45deg);
}
.NavToggle.Nav--is-visible .NavToggle-icon span:nth-child(4) {
left: 50%;
top: 18px;
width: 0%;
}
.Nav {
transition: all 0.5s ease-in-out;
}
.Nav .menu {
margin: 0;
padding: 15px 0;
}
.Nav .menu .menu-item {
list-style: none;
}
.Nav .menu .menu-item > a {
color: #fff;
display: block;
padding: 10px 20px;
text-decoration: none;
}
.Nav--mobile {
background-color: #2d2d2d;
height: 100%;
overflow: auto;
position: fixed;
right: -300px;
top: 0;
width: 300px;
z-index: 2000;
}
.Nav--mobile.Nav--is-visible {
right: 0;
}
.SiteContainer.Nav--is-visible {
right: 300px;
}
Sass
Javascript
Plugin
/**
* Objectiv Mobile Menu
*/
(function() {
'use strict';
if ('object' !== typeof window.Objectiv) {
window.Objectiv = {};
}
window.Objectiv.mobileMenu = function(options) {
if ('undefined' === typeof options.menu)
return false;
var container = document.querySelector(options.container),
menu = document.querySelector(options.menu),
toggle = document.querySelector(options.toggle);
if (!container || !menu || !toggle) return;
function toggleMenu() {
container.classList.toggle('Nav--is-visible');
menu.classList.toggle('Nav--is-visible');
toggle.classList.toggle('Nav--is-visible');
if (toggle.classList.contains('Nav--is-visible')) {
toggle.setAttribute('aria-expanded', true);
menu.setAttribute('aria-hidden', false);
} else {
toggle.setAttribute('aria-expanded', false);
menu.setAttribute('aria-hidden', true);
}
}
toggle.addEventListener('click', function(e) {
e.preventDefault();
toggleMenu();
});
}
})();
Usage
Objectiv.mobileMenu({
container: '.SiteContainer',
menu: '.Nav--mobile',
toggle: '.NavToggle'
});