Responsive drop down menu with CSS media queries & jQuery

Responsive drop down menu with CSS media queries & jQuery

Or in other words, display a custom (mobile?) menu at a user defined breakpoint.

So the steps are

1)Detect browser window size onload
2)Apply appropriate menu
3)Monitor window size
4)Apply appropriate menu at breakpoint

How we’re going to do it

1)Detect window size with CSS media Queies and jQuery onload
2)Apply add CSS helper class if window size is smaller then our breakpoint & show our navigation ‘Toggler’
3)Continue to monitor window size
4)Add/remove CSS helper class and menu ‘toggler’ accordingly

Menu Structure & Setup

Use what you want, but this happens to be what I was using last.

[html]</pre>
<div id="nav">
<div class="container">
Navigation <span>+</span>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">What I’ve Done</a></li>
<li><a href="#">What’s Popular</a></li>
<li><a href="#">Contact Me</a></li>
<li><a href="#">Blog</a></li>
</ul>
</div>
</div>
<pre>
[/html]

And some basic CSS to display a horizontal navigation menu and a media query that will set the p element in our navigation (the toggler) to block.

[css]
/*=========== helper classes =====================*/
p.mobile-nav {
display: none;
margin-bottom: .5em;
font-size: 1.4em !important; }

p.mobile-nav span {
font-size: 1.3em; }

.mobile li {
display: block;
width: 43%;
border-bottom: 1px solid #ccc;
float: left;
padding: 10px 0;
font-size: 1.2em;
}

@media only screen
and (max-width : 768px) {
p.mobile-nav {
display: block; }
}
[/css]

Detect window size with CSS media Queries and jQuery onload

For our purpose, 768px will be our break point wich also happens to be the width (in landscape) of the (old) iPad. It’s at this point, I felt that current navigation was too difficult to use. You can choose whatever you’d like.

We’ve already set the p.mobile to block , thus un-hiding and making it available as our ‘toggler’. Now, we need to detect window size. I’m going to take a object literal aproach to this, writing a method for each piece of the puzzle. But first some set up…

[javascript]
(function() {
navigation: $(‘#nav ul’),
navContainer: $(‘div#nav’),

windWidth: function(){

var windWidth = $(window).width(),
nav = adaptiveNav.navigation;

if (windWidth < 768){
$(adaptiveNav.navContainer).removeClass(‘mobile’);
nav.show();
};
},

})();
[/javascript]

Get the window width, store it in a variable. Then test to see if the window is larger or smaller then the break point. If it’s smaller, add the ‘mobile’ class. When can then use our new hook to apply the ‘.mobile li’ helper class.

Note, an alternative all – CSS route would be:

[css]

@media only screen
and (max-width : 768px) {
p.mobile-nav {
display: block;
}
.mobile li {
display: block;
width: 43%;
border-bottom: 1px solid #ccc;
float: left;
padding: 10px 0;
font-size: 1.2em;
}
}
[/css]

Toggle the menu

[javascript]
//Handles toggling nav
toggleNav: function(){
$(‘#nav p’).on(‘click’, function() {
var addSubText = $(‘.mobile-nav span’).text(),
addSub = $(‘.mobile-nav span’),
//let’s not let our variables get out of hand…
nav = adaptiveNav.navigation,
config = adaptiveNav.config;

nav[config.effect]();

if (addSubText === ‘+’) {
$(‘.mobile-nav span’).html(‘-‘);
}else{
$(‘.mobile-nav span’).html(‘+’);
}
})
},
[/javascript]

Add a new method to handle this. Also, toggle ‘-‘ and ‘+’ symbols to denote navigation showing or hiding.

Add configuration and init method

[javascript]
config: {
effect: ‘slideToggle’,
speed: 500
},

init: function(config) {
$.extend(this.config, config);

this.toggleNav();

//call on load
this.windWidth();
//and on resize
$(window).on(‘resize’, function() {
adaptiveNav.windWidth();
});
},
[/javascript]

The init function calls the windWidth function on load to get the initial window size and then continues to monitor to the size on window resize.

Initialize

[javascript]
adaptiveNav.init();
[/javascript]

Finished Code

[javascript]

(function() {

var adaptiveNav = {
//Now, let’s take care of the mobile navigation
//hide navigation on load
navigation: $(‘#nav ul’),
navContainer: $(‘div#nav’),

config: {
effect: ‘slideToggle’,
speed: 500
},

init: function(config) {
console.log(config);
console.log(this.config);
$.extend(this.config, config);

this.toggleNav();

//call on load
this.windWidth();
//and on resize
$(window).on(‘resize’, function() {
adaptiveNav.windWidth();
});
},

//Handles toggling nav
toggleNav: function(){
$(‘#nav p’).on(‘click’, function() {
var addSubText = $(‘.mobile-nav span’).text(),
addSub = $(‘.mobile-nav span’),
//let’s not let our variables get out of hand…
nav = adaptiveNav.navigation,
config = adaptiveNav.config;

nav[config.effect]();

if (addSubText === ‘+’) {
$(‘.mobile-nav span’).html(‘-‘);
}else{
$(‘.mobile-nav span’).html(‘+’);
}
})
},

//Add the mobile class if the browser window in 480px or smaller
windWidth: function(){

var windWidth = $(window).width(),
nav = adaptiveNav.navigation;

if (windWidth <= 767) {
$(adaptiveNav.navContainer).addClass(‘mobile’);
}else if(windWidth > 767){
$(adaptiveNav.navContainer).removeClass(‘mobile’);
nav.show();
};
},

};

adaptiveNav.init({
effect: ‘slideToggle’
});

});

[/javascript]

Demo