We are rebuilding. Join us.

We are rebuilding our site—live at building.seesparkbox.com. Join us, real-time, as the site evolves. It will be ugly at times. Sometimes it will be downright broken. But it will always be transparent and real. You can even check under the hood of the public repo on Github and share your ideas. Crazy, are we? Read why we're doing this.

Let’s be more than friends.

We really
like to share

The Foundry is our place to share articles, tutorials, events, and more. Search for a topic or just read everything.

Responsive Web Design and JavaScript

Responsive Web Design and JavaScript

If you haven’t read Ethan’s article, stop now, read it, and then come back here.

Now, let's talk about some responsive web design. For over a year now, we've been developing responsive websites almost exclusively at Sparkbox, and I’ve found something missing in our responsive tool belt – a good way to handle JavaScript.

Example

Recently, I was working on a secondary navigation with two sections. At media queries for smaller sized screens, the navigation had links to show and hide each section using jQuery animations. This posed a problem, however. After they were hidden, jQuery left style="display: none" on the elements. After resizing the browser and jumping to a media query for a larger sized screen, these elements should have been shown without the need for the additional links, but they were hidden because of the inline style. 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Media Query Testing</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<nav id="secondary-nav" class="secondary">
<div class="button-group">
<a href="#quick-links" class="mobile-button">Quick Links</a>
<a href="#site-search" class="mobile-button search-button">Site Search</a>
</div>
<ul id="quick-links" class="quick-links-menu secondary-menu">
<li><a href="#" title="">News</a></li>
<li><a href="#" title="">Account Info</a></li>
<li><a href="#" title="">FAQ</a></li>
<li><a href="#" title="">Help</a></li>
</ul>
<fieldset id="site-search" class="site-search secondary-menu">
<input class="search-field" type="search" name="site-search">
<input class="search-submit" type="submit" value="Search">
</fieldset>
</nav>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/mediaCheck.js"></script>
<script src="js/script.js"></script>
</body>
</html>
view raw html This Gist brought to you by GitHub.

Now, I know that everyone likes to say that only developers change their browser sizes to see how things respond. There are real problems with this type of thinking. What if the user maximizes their window or makes it smaller based on the content? This might switch media queries, triggering a break in the secondary navigation. Here's another example that is pretty relevant – what if the controlling media query is somewhere around 900px? A simple orientation change of an iPad would cause these navigation elements to disappear. Oops. Do you care now?

Solution

The solution to this problem lies in the elusive matchMedia method; it provides events triggered by media queries.

In order to run code based on media queries, I'm using mediaCheck (a wrapper I've written around matchMedia to fire events when entering or leaving a designated media query) to trigger the cleanup code when entering larger media queries.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
$(function() {
function secondaryNavLinks( e ) {
var $toOpen = $( $( e.target ).attr( "href" ) + ":hidden" );
 
$( "#secondary-nav" ).children( ".secondary-menu:visible" ).slideUp();
$toOpen.slideDown();
 
e.preventDefault();
}
function secondaryNavCleanup() {
$( ".secondary-menu" ).removeAttr( "style" );
}
$( ".secondary a" ).on( "click", secondaryNavLinks );
mediaCheck({
media: '(min-width: 800px)',
entry: function() {
secondaryNavCleanup();
},
});
});
view raw js This Gist brought to you by GitHub.

Now when the 600px media query is fired, it will remove the style attributes and all is well with the secondary nav.

mediaCheck provides a nice wrapper to easily turn code on and off based on media queries. Switching behaviors and cleaning up code between media queries is now made simple. JavaScript mischief managed.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
var mediaCheck = function(options) {
var mq,
matchMedia = window.matchMedia !== undefined;
if (matchMedia) {
mqChange = function(mq, options) {
if (mq.matches) {
options.entry();
} else {
options.exit();
}
};
createListener = function(mqDetails) {
mq = window.matchMedia(mqDetails.media);
mq.addListener(function() {
mqChange(mq, mqDetails);
});
mqChange(mq, mqDetails);
};
createListener(options);
}
};
view raw js This Gist brought to you by GitHub.

Take it out for a test drive, kick the tires, and look under the hood. Feel free to ask questions and contribute, and let's move the web forward together.

 

Keep up with new posts in the Foundry by subscribing to our weekly email: The Spark.