Skip to content

Instantly share code, notes, and snippets.

@old-campos
Created March 3, 2013 19:55
Show Gist options
  • Save old-campos/5077976 to your computer and use it in GitHub Desktop.
Save old-campos/5077976 to your computer and use it in GitHub Desktop.
A CodePen by Francisco Campos. css3 animated, responsive navigation menu (with submenu) for unknown number of menu items. - The ridiculously long name says it all really... The code (particularly the css) could do with cleaning up in a few places but basically this is a responsive navigation menu technique that doesn't rely on falling back to se…
<nav role="navigation" class="nav">
<a class="menu-toggle" href="#head-nav">
<span aria-hidden="true" class="icon-menu"></span><span class="menu-toggle-text"> menu</span>
</a>
<ul id="main-menu" class="top-nav menu clearfix">
<li class="menu-item">
<a href="http://codepen.io">Home</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">About</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">Archives</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">Categories</a>
<ul class="sub-menu">
<li class="menu-item">
<a href="http://codepen.io">Reading</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">Writing</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">Arithmatic</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">Something Long</a>
</li>
<li class="menu-item">
<a href="http://codepen.io">Something Else</a>
</li>
</ul>
</li>
<li class="menu-item">
<a href="http://codepen.io">Contact</a>
</li>
</ul>
</nav>
/*
Responsive nav menu with sub menus on larger screens.
built using very limited amount of js (javascript adds a couple of css classes) and to deal with an unknown number of menu items (used in several WordPress themes).
many further enhancements could easily be made (for example I normally include js to allow keyboard focus to automatically expand the collapsed menus) outside the scope of this demo.
The CSS could do with a bit of a clean up at the moment and the styling has intentionally been left very basic for this demo but the key points should still be clear!
*/
/**********
MOBILE MENU
**********/
$('.menu-toggle').click(function(e){
//click event for left clicks only! http://www.jacklmoore.com/notes/click-events
if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey)) {
e.preventDefault();
if($(this).parent().find('.menu').hasClass('expanded-mobile-menu')){
$(this).removeClass('expanded-menu-toggle').parent().removeClass('nav-expanded').find('.menu').removeClass('expanded-mobile-menu');
}else{
$(this).addClass('expanded-menu-toggle').parent().addClass('nav-expanded').find('.menu').addClass('expanded-mobile-menu');
}
}
});
@import "compass";
/****
SETUP
****/
@import url(http://fonts.googleapis.com/css?family=Quattrocento+Sans);
$menucolour:#333;
$highlight:#eeeeaa;
$lighttext:#eee;
@include font-face("symbolset", font-files("http://tedworthandoscar.co.uk/demos/fonts/ss-standard.woff", "http://tedworthandoscar.co.uk/demos/fonts/ss-standard.ttf", "http://tedworthandoscar.co.uk/demos/fonts/ss-standard.svg"), "http://tedworthandoscar.co.uk/demos/fonts/ss-standard.eot");
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: 'symbolset';
font-style: normal;
speak: none;
font-weight: normal;
vertical-align:top;
}
.icon-menu:before {
content: "\eD50";
}
/************
THE REAL DEAL
************/
body{
background:#ddc;
font-family: 'Quattrocento Sans', Helmet, Freesans, Tahoma, Geneva, sans-serif;
}
a{
@include transition(color 800ms ease-in-out, background 800ms ease-in-out);
}
.nav {
padding:2em 0;
font-size:1em;
letter-spacing:0.1em;
text-align: center;
.menu-toggle{
position:relative;
z-index:2;
display: block;
margin:0;
padding: 0.5em 0;
background-color:#ddc;
text-decoration: none;
text-align:center;
font-size:1.4em;
color:$menucolour;
&:hover, &:focus{
color:$lighttext;
background-color: darken($menucolour, 2%);
}
}
.menu-toggle-text{
font-size:0.55em;
display:block;
}
.no-js & .menu-toggle{
display:none;
}
.expanded-menu-toggle{
color:$highlight;
background-color: darken($menucolour, 2%);
}
.no-fontface & .icon-menu:before{
display:none;
}
}
/* .menu is visually hidden by default */
.menu {
position:relative;
z-index:1;
background-color:$menucolour;
border: 0;
margin: -1px auto;
overflow: hidden;
padding: 0;
max-height:1px;
min-height:0;
clip: rect(0 0 0 0);
@include box-shadow(inset 0 0 3px 3px rgba(0, 0, 0, 0.2));
@include transition(max-height 600ms ease-out,
min-height 600ms ease-in,
padding 600ms ease-in);
li {
a {
display: block;
padding: 10px 0;
background-color: transparent;
text-decoration: none;
text-align:center;
font-size:1.2em;
color:$lighttext;
@include border-radius(2px);
&:hover, &:focus {
color:$highlight;
background:lighten($menucolour, 10%);
}
}
/* no sub menus for mobile */
ul.sub-menu, ul.children {
display:none;
}
} /* end .menu li */
} /* end .menu */
.no-js .menu, .expanded-mobile-menu{
@include transition(max-height 800ms ease-in,
min-height 500ms ease-out,
padding 400ms ease-in);
/*min/max heights allow me to css transition to height auto for WordPress menus with unknown number of items*/
clip: auto;
min-height:8em;
max-height:100em;
padding:0.5em 0;
}
@media only screen and (min-width: 30.1em) { /*481 ish px*/
.menu {
li {
float:left;
width:50%;
}
}
}
@media only screen and (min-width: 48em) {
.nav {
.menu-toggle{
display:none;
}
}
.menu, .no-js .menu, .expanded-mobile-menu {
/* no longer hidden by default! */
margin:0;
min-height:0;
max-height:999em;
@include border-radius(0);
overflow:visible;
padding:0.7em 0;
background:$menucolour;
@include box-shadow(inset 0 0 3px 3px rgba(0, 0, 0, 0.2));
li {
float:none;
width:auto;
display:inline-block;
position: relative;
vertical-align:middle;
.lt-ie8 &{
/* inline-block fix for old ie (relevant if they're served larger media queries in an IE stylesheet or something similar...*/
display:inline;
zoom:1;
}
a {
padding:0.3em 1em;
color:$lighttext;
&:hover, &:focus {
color: $highlight;
background: lighten($menucolour, 2%);
}
}
/* DROP DOWNS */
ul.sub-menu,
ul.children {
display:block;
position: absolute;
z-index: 2;
top: 100%;
left:0;
white-space:nowrap;
@include transition(max-height 400ms ease-out,
min-height 500ms ease-in,
padding 500ms ease-out,
opacity 500ms ease-in);
background:lighten($menucolour, 2%);
text-align:left;
@include border-radius(0 4px 4px 4px);
/* visually hidden */
opacity:0;
border: 0;
margin: -1px 0;
overflow: hidden;
padding: 0;
max-height:1px;
min-height:0;
li {
display:block;
padding:0.2em 0.4em 0;
a {
font-size:1em;
padding:0.2em 0.5em 0.2em 0.8em;
display:block;
line-height:1.5;
margin:0;
text-align:left;
background:transparent;
&:hover,
&:focus {
background:lighten($menucolour, 4%);
}
}
&:last-child {
a {
border-bottom: 0;
}
}
/* could go deeper here... */
}
}
/* showing sub-menus */
&:hover ul, &.focused ul {
@include transition(max-height 800ms ease-in,
min-height 500ms ease-out,
padding 500ms ease-out,
opacity 800ms ease-out);
/* again using min/max heights to deal with unknown length of lists */
min-height:8em;
max-height:100em;
padding:0.4em 0;
opacity:1;
ul{
min-height:0;
padding:0;
}
}
&:hover > a{
background:lighten($menucolour, 2%);
}
} /* end .menu ul li */
} /* end .menu */
}/* end media query*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment