Accessible Off-canvas Push Menu with jQuery and CSS3
File Size: | 4.05 KB |
---|---|
Views Total: | 3304 |
Last Update: | |
Publish Date: | |
Official Website: | Go to website |
License: | MIT |

Just another jQuery & CSS3 based off-canvas navigation (push menu) that uses JavaScript to dynamically adds WAI-ARIA roles to make your site navigation more accessible.
How to use it:
1. Create a off-canvas navigation with a toggle button and wrap them together with the main content into a wrapper like this:
<div class="site-wrapper"> <div class="main"> <div class="wrap"> <!-- Hamburger menu toggler --> <a href="#navigation" title="navigation menu" aria-label="navigation menu"> Navigation Menu <span class="bar bar-1"></span> <span class="bar bar-2"></span> <span class="bar bar-3"></span> </a> <!-- Main content --> ... </div> </div> <!-- Off-canvas navigation --> <nav id="navigation" role="navigation"> <ul> <li class="active"><a href="#">Home</a></li> <li><a href="#">Works</a></li> <li><a href="#">Contact</a></li> <li><a href="#">About</a></li> <li><a href="#">Blog</a></li> </ul> </nav> </div>
2. The basic CSS styles.
body { overflow-x: hidden; } *:focus { outline: 1px solid #03A9F4; } .main { position: relative; padding: 0 20px; margin-left: 0; -webkit-transition: all 0.3s cubic-bezier(1, 0.1, 0, 0.9); transition: all 0.3s cubic-bezier(1, 0.1, 0, 0.9); -webkit-transform: translateZ(0) translateX(0); transform: translateZ(0) translateX(0); } .main > .wrap { padding: 80px 0; max-width: 1200px; margin: 0 auto; } [data-nav-visible="true"] .main { -webkit-transform: translateZ(0) translateX(300px); transform: translateZ(0) translateX(300px); }
3. Style the hamburger toggle button.
a[href="#navigation"] { display: inline-block; position: absolute; top: 20px; left: 20px; text-indent: -9999px; background: #03A9F4; height: 60px; width: 60px; border-radius: 100%; box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.5); -webkit-transition: all 0.3s cubic-bezier(1, 0.1, 0, 0.9); transition: all 0.3s cubic-bezier(1, 0.1, 0, 0.9); -webkit-transform: translateZ(0) scale(1); transform: translateZ(0) scale(1); } a[href="#navigation"]:hover { opacity: 0.9; } [data-nav-visible="true"] a[href="#navigation"]:before { -webkit-transform: translateZ(0) scale(1); transform: translateZ(0) scale(1); } [data-nav-visible="true"] a[href="#navigation"] .bar { margin-top: -3px !important; } [data-nav-visible="true"] a[href="#navigation"] .bar.bar-1 { -webkit-transform: translateZ(0) rotate(45deg) translateY(0); transform: translateZ(0) rotate(45deg) translateY(0); } [data-nav-visible="true"] a[href="#navigation"] .bar.bar-2 { opacity: 0; } [data-nav-visible="true"] a[href="#navigation"] .bar.bar-3 { -webkit-transform: translateZ(0) rotate(-45deg) translateY(0); transform: translateZ(0) rotate(-45deg) translateY(0); } a[href="#navigation"]:before { content: ''; position: absolute; display: block; height: 100%; width: 100%; border-radius: 100%; -webkit-transform: translateZ(0) scale(0); transform: translateZ(0) scale(0); background: #FF5722; -webkit-transition: all 1s cubic-bezier(1, -0.25, 0, 1.25); transition: all 1s cubic-bezier(1, -0.25, 0, 1.25); } a[href="#navigation"] .bar { display: block; position: absolute; background: white; height: 4px; width: 26px; top: 50%; left: 50%; margin-left: -13px; margin-top: -2px; border-radius: 2px; opacity: 1; -webkit-transform: translateZ(0) rotate(0deg); transform: translateZ(0) rotate(0deg); -webkit-transition: all 0.7s cubic-bezier(1, 0.1, 0, 0.9); transition: all 0.7s cubic-bezier(1, 0.1, 0, 0.9); } a[href="#navigation"] .bar.bar-1 { -webkit-transform: translateZ(0) rotate(0deg) translateY(-8px); transform: translateZ(0) rotate(0deg) translateY(-8px); } a[href="#navigation"] .bar.bar-3 { -webkit-transform: translateZ(0) rotate(0deg) translateY(8px); transform: translateZ(0) rotate(0deg) translateY(8px); }
4. Style the off-canvas navigation.
nav[role="navigation"] { position: fixed; top: 0; left: 0; bottom: 0; padding: 0; overflow: hidden; background: #111; width: 300px; box-sizing: border-box; -webkit-transition: all 0.3s cubic-bezier(1, 0.1, 0, 0.9); transition: all 0.3s cubic-bezier(1, 0.1, 0, 0.9); -webkit-transform: translateZ(0) translateX(-100%); transform: translateZ(0) translateX(-100%); } [data-nav-visible="true"] nav[role="navigation"] { -webkit-transform: translateZ(0) translateX(0); transform: translateZ(0) translateX(0); } nav[role="navigation"] > ul { margin: 0; padding: 40px 0; list-style: none; -webkit-transition: all 0.2s ease 0.3s; transition: all 0.2s ease 0.3s; -webkit-transform: translateZ(0) translateX(100%) scale(0.6); transform: translateZ(0) translateX(100%) scale(0.6); } [data-nav-visible="true"] nav[role="navigation"] > ul { -webkit-transition: all 0.2s ease 0.1s; transition: all 0.2s ease 0.1s; -webkit-transform: translateZ(0) translateX(0) scale(1); transform: translateZ(0) translateX(0) scale(1); } nav[role="navigation"] > ul li.active a { border-left: 2px solid #03A9F4; background: #222; } nav[role="navigation"] > ul a { display: block; padding: 15px 20px; color: white; font-size: 18px; text-decoration: none; border-left: 2px solid transparent; } nav[role="navigation"] > ul a:hover { background: #03A9F4; }
5. Include the latest version of jQuery library from a CDN.
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
6. The core JavaScript to enable the accessible off-canvas menu.
var Nav = function($) { return { init: function() { this.cacheDom(); this.setupAria(); this.bindEvents(); }, cacheDom: function() { this.$site = $('.site-wrapper'); this.$navBtn = this.$site.find('[href="#navigation"]'); this.$navBtnExpanded = this.$site.find('[aria-expanded]'); this.$nav = $('#navigation'); this.$navFirstLink = this.$nav.find('li:first-child a'); this.$navLastLink = this.$nav.find('li:last-child a'); this.$content = this.$site.find('.content'); }, bindEvents: function() { this.$navBtn.on('click', this.toggleMenu.bind(this)); this.$navBtnExpanded.on('keydown', this.setFocus.bind(this)); this.$navFirstLink.on('keydown', this.returnFocusFirst.bind(this)); this.$navLastLink.on('keydown', this.returnFocusLast.bind(this)); }, setupAria: function() { this.$navBtn.attr({ 'role': 'button', 'aria-controls': 'navigation', 'aria-expanded': 'false' }); this.$site.attr({ 'data-nav-visible': 'false' }); }, toggleMenu: function() { var self = $(event.currentTarget); event.preventDefault(); self.attr('aria-expanded') === 'true' ? this.closeMenu() : this.openMenu(); }, openMenu: function() { this.$site.attr({ 'data-nav-visible': 'true' }); this.$navBtn.attr({ 'aria-expanded': 'true' }); }, closeMenu: function() { this.$site.attr({ 'data-nav-visible': 'false' }); this.$navBtn.attr({ 'aria-expanded': 'false' }); }, returnFocusFirst: function() { if (event.keyCode === 9) { if (event.shiftKey) { event.preventDefault(); this.$navBtn.focus(); } } }, returnFocusLast: function() { if (event.keyCode === 9) { if (!event.shiftKey) { event.preventDefault(); this.$navBtn.focus(); } } }, setFocus: function() { var self = $(event.target); if (event.keyCode === 9) { if (self.attr('aria-expanded') == 'true') { if (!event.shiftKey) { event.preventDefault(); this.$navFirstLink.focus(); } else { if (event.shiftKey) { event.preventDefault(); this.$content.focus(); } } } } } } }(jQuery); Nav.init();
This awesome jQuery plugin is developed by dapacreative. For more Advanced Usages, please check the demo page or visit the official website.