Responsive CSS3 Multi-Level, Fly-Out Menu (with JavaScript enhancement)
Here is another responsive menu that adds a desktop layout to the earlier CSS3 Multi-Level, Off-Canvas Mobile Menu (no JavaScript).
This menu differs from the CSS-only version only in that it uses a smidge of JavaScript to close all the menus/sub-menus, and hide the off-canvas menu again, in one click (in mobile view), whereas the CSS-only version requires all opened sub-menus to be closed in turn, before the user is able to send the menu back off-canvas and bring content back in to view. Please read the Notes section for details about JavaScript enhancement.
Desktop (> 960px): Look left to see the always-visible vertical menu, and hover/tap to trigger subs...
Mobile (< 960px): Click/tap that ☰ icon in the top-right corner to open the "off-canvas" menu...
Features
A CSS3, responsive menu that;
- Supports unlimited sub-menus, of infinite depth *
- Uses a nested list format
- Uses CSS3 transitions to animate the "off-canvas" slide effect (no JavaScript)
- Uses the "advanced checkbox hack" to activate "off-canvas" sub-menus (for Android/iOS)
- Uses "translate3d" to force hardware acceleration in WebKit (no flicker)
- Has a "Go-Up" option to change the vertical direction of fly-out sub-menus
- Is only slightly enhanced with JavaScript and degrades gracefully with it turned off
* Although an infinite number of nested sub-menus is possible, you'll probably want to stop at 2 or 3 deep due to the sub-menus that progressively fly across the screen in desktop view.
Please view the source of this web page to grab the JS, CSS and HTML markup.
Go-Up (desktop view)
Long nested menus will eventually fall off the bottom of the screen. To counter this, a "go-up" option is available to change the vertical direction of sub-menus. In otherwords, to make them go upwards. The "Focus on Function > Services" menu is an example of this.
To trigger the "go-up" menu, just put a class of "go-up" on the parent <li> tag;
<li class="go-up"><a href="#">Services</a> <label for="fof-services" class="toggle-sub" onclick="">►</label>
<input type="checkbox" name="nav" id="fof-services" class="sub-nav-check"/>
<ul id="fof-services-sub" class="sub-nav">
<li class="sub-heading">Services <label for="fof-services" class="toggle" onclick="" title="Back">►</label></li>
<li><a href="#">Content Management</a></li>
<li><a href="#">Graphic Design</a></li>
...
CSS Transforms and the "position:fixed" bug in Safari
When CSS Transforms are used (as this menu does), there is a known buggy behaviour in Safari that affects child "position:fixed" elements. What happens is that it seemingly forces them to adopt a "position:absolute" placement, while forcing their immediate parents to "position:relative". This causes some very strange (and frustrating) results. There is an easy fix here though - apply this CSS if you have any "position:fixed" elements inside ".container";
/* #### - corrects 'unfixing' bug in Safari - #### */
@media screen and (-webkit-min-device-pixel-ratio:0) { .container { -webkit-transform:none !important } }
Notes (JavaScript enhancement for mobile view)
The first change to the CSS-only version of this responsive menu is that all the checkboxes are named, e.g;
<input type="checkbox" name="nav" id="something-unique" class="sub-nav-check" />
And the bit of JavaScript below is used to remove all checks from checkboxes, thus closing all of the menus/sub-menus at once (in mobile view) instead of needing to close each in turn. I've also included a snippet that adds a class of "js" to the <html> element when JavaScript is enabled which, when coupled with the appropriate CSS, makes the menu degrade back to the CSS-only version when JavaScript is turned off;
<script>
document.documentElement.className = 'js'; // adds class="js" to <html> element
function uncheckboxes(nav){
var navarray = document.getElementsByName(nav);
for(var i = 0; i < navarray.length; i++){
navarray[i].checked = false
}
}
</script>
The JavaScript function is called inside an additional × label, placed just above the closing #menu div, which closes the menu and sends all mobile navigation back off-canvas. Note that there is no "for" attribute in the label - for some reason, things are a bit buggy with it included;
<label class="toggle close-all" onclick="uncheckboxes('nav')">×</label>
</div><!-- closing "#menu" -->
Now to make the new × label look pretty, and also move the large "back" ◄ arrows out of the way, add the following CSS to the mobile area of the stylesheet. Note the ".js" selectors that only apply when JavaScript is enabled;
#menu .close-all { display:none }
.js #menu .close-all { display:inline }
.js #menu .toggle { top:0; z-index:9999 }
.js #menu .sub-nav .toggle { left:0.15em; width:1em }
Finally, hide the × label when in desktop view by adding this to the desktop CSS;
.js #menu .close-all { display:none }
Compatibility
- Desktop: IE7+ (no fly/fade effect in IE7/8/9) / Mobile: IE9+ (no slide effect in IE9)
- Chrome
- Safari
- Firefox
- Opera
- Android
- iOS
Please be aware that touch screen desktop/tablet users have to tap the indicator arrows to open sub-menus, and fly-out sub-menus are likely to obscure page content until another link is clicked (see the iOS 'Sticky Hover' fix).
I haven't been able to test in other browsers/devices but feedback is always welcome. Contact me if anything goes awry in other browsers.
Related
- Also see CSS3 Multi-Level, Off-Canvas Mobile Menu (no JavaScript)
- Also see CSS3 Multi-Level, Off-Canvas Mobile Menu (with JavaScript enhancement)
- Also see CSS3 Multi-Level, Off-Canvas Mobile Menu (with JavaScript IE7/8 support)
- Also see Responsive CSS3 Multi-Level, Drop-Down Menu (no JavaScript)
- Also see Responsive CSS3 Multi-Level, Drop-Down Menu (with JavaScript enhancement)
- Also see Responsive CSS3 Multi-Level, Drop-Down Menu (with JavaScript enhancement + keyboard 'tab-to' support)
- Also see Responsive CSS3 Multi-Level, Drop-Down Menu (SwiftClick - no 300ms delay + tap-to-close drop-downs)
- Also see Responsive CSS3 Multi-Level, Push/Slide Menu (no JavaScript)
- Also see Responsive CSS3 Multi-Level, Push/Slide Menu (with JavaScript enhancement)
- Also see Responsive CSS3 Multi-Level, Push/Slide Menu (with JavaScript enhancement + keyboard 'tab-to' support)
- Also see Responsive CSS3 Multi-Level, Fly-Out Menu (no JavaScript)
- Also see Responsive CSS3 Multi-Level, Fly-Out Menu (with JavaScript enhancement + keyboard 'tab-to' support)
Freebies
Looking for more freebies for your website? Grab a bunch of free PHP, CSS and JavaScript goodies, from flat file CMS' to RSS managers to responsive CSS menus, galleries and sliders.