Making Your WordPress Theme Responsive: Core Features
- Handling Navigation
- Handling Images
- Handling Widgets
- Wrapping Up
So far, you’ve seen multiple ways to make a website responsive. Now it’s time to really dig in and combine those techniques with WordPress’ unique capabilities.
In Chapter 3, you learned how to apply your responsive CSS to a WordPress theme. You also got an in-depth look at WordPress’ generated CSS classes and created some default styles for what are considered the “essential” ones. From here on out, you’ll go even further, focusing on two types of features: core and blog.
This chapter looks at some of the core features of WordPress instrumental to a good User Experience. The next chapters are about using what WordPress provides developers and leveraging those tools to create better responsive sites. That said, you’ll look at three areas of development in this chapter: navigation menus, images, and widgets.
Handling Navigation
Responsive navigation techniques are bountiful in books and blog posts; many developers have come up with their own implementations for navigation menus on responsive sites. Brad Frost outlines some of the most popular ones at http://rwdwp.com/32.
In this section, we will look at a few popular techniques and how they look on the Millennium Flights site, and then decide what’s best.
A Look at Popular Techniques
If you looked at Brad Frost’s post, you’ll see that he also wrote a second one and linked to several others. In other words, there are lots of navigation menu patterns to choose from.
We will explore three possible options for the Millennium Flights navigation: Do Nothing (or Top Nav), Jump to (or Footer nav), and the Select box...plus a bonus technique that may surprise you. While we won’t be implementing it, we will also look at the Off-Canvas technique, which is a bit more advanced
Do Nothing (or Top Nav)
This is the easiest one to implement. You simply leave the navigation as is at the top of your site; you’ll see what the “technique” looks like in Figure 4.1.
Figure 4.1 Millennium Flights with the “Do Nothing” responsive navigation technique.
As long as your navigation styles are not limited by a specific Media Query, they will apply to the entire site if you employ the Do Nothing technique. It is easy to apply because you don’t have to make changes to your code, but there are some pitfalls. Luckily the navigation for Millennium Flights uses big text, but imagine a site with smaller text using this approach. Users may have difficulty selecting the menu items on smaller screens (Figure 4.2).
Figure 4.2 On the left is how this website navigation renders on an Android phone. On the right, you see what happens when you resize the browser. In both cases, the nav appears small and difficult to press without zooming.
The other big issue with the technique is that as a user adds more menu items, the height of the page increases. You don’t want to have a situation where the user only sees a logo and menu items on page load on a smart phone.
“Do Some Things”
I have a slight modification to this approach, which I’ve very cleverly called “Do Some Things.” It’s the idea that functionally, nothing about the navigation changes; it doesn’t change locations or implementations. It’s still an unordered list at the top of the page. That is, it will stay in the same place and it will be a list of menu items, exactly the same on both layouts. However, you do make slight tweaks and changes to the CSS, optimizing it a little bit for mobile. An example can be seen on my personal site, Casabona.org (Figure 4.3).
Figure 4.3 Casabona.org’s navigation on both mobile and desktop layouts. The position of the navigation doesn’t change, but the items become more button-like on mobile to make pressing them easier for the user.
Not too much has changed in the overall webpage layout, but you’ll see each menu item on smaller screens is its own individual button (as opposed to the contiguous grey bar on wider screens), and the font gets a little bolder on smaller screens.
This slightly modified approach still runs into some of the pitfalls of the “Do Nothing” approach, like taking up a lot of screen real estate on small screens.
Jump to or Footer Anchor
In this technique, as the screen gets smaller, the navigation is replaced by a single link that jumps the user to navigation in the footer. This, like the “Do Nothing” approach, is easy to implement, but it saves on screen real estate, as the menu is no longer at the top to take up space (Figure 4.4).
Figure 4.4 The Jump to navigation. The menu items are replaced with a single link that brings users to the bottom of the page.
There are a couple of ways to code this technique. The most common one is to use CSS’s display: none; to hide the navigations that should not be in use. For example, if this is the header and footer markup:
Header Markup
<nav id="main"> <div class="full"> <?php wp_nav_menu( array('menu' => 'Main' )); ?> </div> <div class="jump"> <a href="#footernav">Jump to Nav</a> </div> </nav>
Footer Markup
<nav id="footernav"> <?php wp_nav_menu( array('menu' => 'Main' )); ?> </nav>
The CSS would look like this:
nav#main .full{ display: none; } #footernav ul{ margin: 0; padding: 0; } #footernav li{ font-size: 1.5em; border-bottom: 1px solid #FFFFFF; } #footernav li a{ padding: 10px; } ... @media screen and (min-width: 34.188em){ ... nav#main .full{ display: block; } #footernav, nav#main .jump{ display: none; } ... }
This code works fine, but it’s forcing the user to download code that he isn’t going to see. Later in this section, you are going to see how this method can be improved using RESS.
Aside from the extra code, this experience might be a jarring one for the user. The page view would change from the top of the page to the bottom without any scrolling or animations, changing everything the user was looking at; it’s not very smooth. A better solution, and one that takes into account the issues we’ve seen with the techniques we’ve looked at, would be to convert the navigation to a Select box for mobile.
The Select Box
The Select box is a clean, user-friendly method that places the navigation at the top of the page without taking up too much screen space. One drawback is that it’s not as easy to implement as the previous methods because you actually need to code up two separate menus—one normal menu, and one inside of a select box (Figure 4.5).
Figure 4.5 The Select box navigation approach clears up a lot of room while still keeping navigation at the top; however, the user still has to download two different navigation menus.
Let’s think outside of WordPress for a second, and look at the HTML structure for a select menu navigation:
<select onchange="location=this.options[this.selectedIndex].value;"> <option value="" selected="selected">Go to...</option> <option value="/home/">Home</option> <option value="/about/">About</option> <option value="/destinations/">Destinations</option> <option value="/contact/">Contact</option> </select>
While this seems like a pretty standard implementation, it’s actually going to take a little bit of work to get this properly working in WordPress because it changes the entire structure of the menu. Luckily, WordPress allows developers to do just that with the Walker_Nav_Menu class. A “Walker” in programming is a way to traverse, or process, tree-like data structures, which create hierarchical data. In this case, it’s traversing HTML to create an unordered list of nav items. You will create a file called Select_Nav_Walker.php, where you will write a class that extends Walker_Nav_Menu, using the four functions it uses to display the menu:
class Select_Nav_Walker extends Walker_Nav_Menu { public function start_lvl(&$output, $depth){} public function end_lvl(&$output, $depth){} public function start_el(&$output, $item, $depth, $args){} public function end_el(&$output, $item, $depth){} }
The functions start_lvl and end_lvl print the opening and closing elements for the menu; by default this is <ul> and </ul>. You will actually add the new markup (the <select> tags from above) in a different area, so both of those functions will remain as is: blank.
The other two functions, start_el and end_el, will be used to print the individual menu items. end_el is incredibly simple:
public function end_el(&$output, $item, $depth){ $output .= "</option>\n"; }
The function is just one line—the markup that closes the menu item. By default, it is </li>, but since this is a select menu, you are changing it to </option>. The variable $output is what this class continually adds to before sending it back to be printed on the screen. Because of that, it’s important to use “.=” and not just “=”. If you don’t, your menu will just be </option>.
The start_el function is a little more complicated than that, and it will make use of the $item argument passed to it:
public function start_el(&$output, $item, $depth, $args){ $item->title = esc_attr($item->title); parent::start_el(&$output, $item, $depth, $args); $output .= ' <option value="'. $item->url .'">'. $item->title; }
The first line escapes the title, converting special characters to HTML entities. Then it calls the parent function (remember this class is extending the built-in Walker_Nav_Menu class), which will apply all CSS classes that would otherwise be applied. Finally, we send the <option> element to $output. $item is an array that has several values, including url and title.
That completes the class, with the entire thing looking like this:
class Select_Nav_Walker extends Walker_Nav_Menu { public function start_lvl(&$output, $depth){} public function end_lvl(&$output, $depth){} public function start_el(&$output, $item, $depth, $args){ $item->title = esc_attr($item->title); parent::start_el(&$output, $item, $depth, $args); $output .= ' <option value="'. $item->url .'">'. $item->title; } public function end_el(&$output, $item, $depth){ $output .= "</option>\n"; } }
You can either place it directly into functions.php or in its own file, including it in functions.php.
After that, you’ll need to attend to the header.php markup, which looks like this:
<nav id="main"> <div class="full"> <?php wp_nav_menu( array('menu' => 'Main' )); ?> </div> <div class="select-menu"> <?php wp_nav_menu(array( 'menu' => 'Main', 'walker' => new Select_Nav_Walker(), 'items_wrap' => '<select ONCHANGE="location=this.options[this.selectedIndex]. value;"><option>Go to..</option>%3$s</select>', 'container' => false ) ); ?> </div> </nav>
You will show/hide the proper menu the same way you did with the Footer Anchor technique, but we will explore a better option later in this section.
What should be pointed out here are the new entries for the select-menu version of wp_nav_menu(). There are three new arguments being passed to it:
- walker: The value of the Walker is the instantiation of your Select_Nav_Walker class. This tells WordPress to use this walker instead of the default to construct the menu.
- items_wrap: By default, this is the <ul> wrapper for the normal walker. Since your walker is for a select menu, the appropriate markup should be sent. You’ll also notice the %3$s. This is necessary to make sure $output is included.
- container: This by default wraps the entire list in a div, which we don’t need to do.
That’s everything. Now you should have the regular menu at full width and the select menu for smaller screens. This still has the issue of multiple menus being downloaded, but we will fix that later.
Off Canvas
This technique is by far the most advanced one we’ll cover, but it’s also the slickest. With this method, you’ll have your main content on screen and then a button (or even swipe) to reveal more content off to the left or right. This is used by a lot of mobile applications to place the navigation on the left side, hidden away (Figure 4.6).
Figure 4.6 Forecast.io, an incredible mobile website, employs the off canvas technique.
This technique completely frees up screen space so the user only sees content. The biggest drawback is the difficulty in implementing it. Depending on how you do it, you could be hiding content, and you will almost definitely use JavaScript (probably jQuery) for the animation effect. It would also, in essence, create an entirely new page section you would have to manage. If you want to see this technique in action or take a crack at it yourself, Jason Weaver and Luke Wroblewski have released code, resources, and examples at http://rwdwp.com/34 (Figure 4.7).
Figure 4.7 The Off Canvas website has a live demo, sample code, and resources for those interested in trying it out.
This is not the only implementation of the off canvas approach. If menus (or any content) slide down from the top or up from the bottom, it’s also considered off canvas, which is really just the viewable area on the screen. Due to its popularity, an open source JavaScript plugin was created to easily implement it. It’s called responsive-nav.js. Let’s look at implementing that into the Millennium Flights theme.
responsive-nav.js
In Chapter 3, we saw some questions that should be asked when considering using some piece of JavaScript; questions like, “Do I need this?” and “How large is the file?” Truth be told, we really don’t need to use responsive-nav.js. However, it is one of the best and most lightweight implementations of the off canvas approach out there. At 1.7 KB, it’s considered small by anyone’s standard.
Everything you’ll need to implement this can be found at http://rwdwp.com/26 (Figure 4.8).
Figure 4.8 The Responsive Nav home page, illustrating how the JavaScript works.
A few things need to happen in order to make responsive-nav.js work in the Millennium Flights theme. First, you’ll need to enqueue the script (after downloading the files). Since there is already a function to do that in the theme, you can just add a new line to it:
function mf_scripts() { wp_enqueue_style( 'googlewebfonts', 'http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' ); wp_enqueue_script( 'responsivenav', TEMPPATH.'/js/responsive-nav.min.js', array()); echo '<!--[if lt IE 9]>'; echo '<script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script>'; echo '<script src="'. TEMPPATH .'/js/respond.min.js"> </script>'; echo '![endif]-->'; }
Since the script requires the containing div to have a CSS ID, you’ll have to modify the nav function slightly. In header.php, change the wp_nav_menu function to this:
<nav id="main"> <?php wp_nav_menu( array('menu' => 'Main', 'container_id' => 'top-menu')); ?> </nav>
You’re adding one more argument, container_id, which will add id=”top-menu” to the div containing the nav menu. Then it’s time to add the CSS.
From the downloaded files, you’ll also find a style sheet called responsive-nav.css. You can copy that CSS into your theme’s style.css file, but you’ll need to make some modifications. This will go before any Media Queries:
#top-menu ul { margin: 0; padding: 0; width: 100%; display: block; list-style: none; } #top-menu li { width: 100%; } .js #top-menu { clip: rect(0 0 0 0); max-height: 0; position: absolute; display: block; overflow: hidden; zoom: 1; } nav.opened { max-height: 9999px; }
This is a slight modification of the default CSS, changed only to match our new menu selector. The same thing goes for the CSS added after the first Media Query:
@media screen and (min-width: 34.188em){ .js #top-menu { position: relative; } .js #top-menu { max-height: none; } #nav-toggle { display: none; } ... }
Finally, there is a bit of JavaScript that should go before the </body> tag. To insert it into the theme, we can use the wp_footer action:
function mf_responsive_nav(){ echo '<script> var navigation = responsiveNav("#top-menu"); </script>'; } add_action('wp_footer', 'mf_responsive_nav');
This will tell responsive-nav.js to look for the div with the ID top-menu and apply the changes to the menu in that container. Once that is done, you should be able to refresh your page and see the results (Figure 4.9).
Figure 4.9 Millennium Flights with the default settings for responsive-nav.js. Most of what’s seen here is customizable through JavaScript or CSS.
Most of what can be seen in the screenshot is customizable using CSS or the arguments you pass to the responsiveNav() function. In the final version of the theme, instead of the text, “Menu,” the common menu icon (often called the “hamburger” for some unfortunate reason) is used.
Changing Navigation on the Server Side
Up until this point, the techniques you’ve been using relied completely on CSS—namely showing and hiding navigation based on breakpoints. However, in Chapter 3, you saw a function that could be especially helpful for navigation: mf_is_mobile_device(). Using this, you can choose to conditionally show one version of the site’s navigation over another instead of loading both. Let’s first look at the select box navigation. Instead of having this:
<nav id="main"> <div class="full"> <?php wp_nav_menu( array('menu' => 'Main' )); ?> </div> <div class="select-menu"> <?php wp_nav_menu(array( 'menu' => 'Main', 'walker' => new Select_Nav_Walker(), 'items_wrap' => '<select ONCHANGE="location=this.options[this.selectedIndex]. value;"><option>Go to..</option>%3$s</select>', 'container' => false ) ); ?> </div> </nav>
...we can have something much cleaner, and requiring much less CSS:
<nav id="main"> <?php if(!ISMOBILE){ wp_nav_menu( array('menu' => 'Main', 'container_id' => 'top-menu')); }else{ wp_nav_menu(array( 'menu' => 'Main', 'walker' => new Select_Nav_Walker(), 'items_wrap' => '<select ONCHANGE="location=this.options[this.selectedIndex]. value;"><option>Go to..</option>%3$s</select>', 'container' => false ) ); } ?> </nav>
Notice there isn’t an extra class to hide one menu over the other. It simply says, “If the user is not on a mobile device, print the normal menu. Otherwise, print the select box menu.” This means the user isn’t downloading two sets of navigation, and you don’t have to write extra CSS to hide or show that navigation based on breakpoints.
The same thing can be done with the Jump to or Footer Anchor approach. In header.php, you’ll have:
<nav id="main"> <?php if(!ISMOBILE){ wp_nav_menu( array('menu' => 'Main', 'container_id' => 'top-menu')); }else{ echo '<a href="#footernav">Jump to Nav</a>'; } ?> </nav>
This is constructed just like the Select box code above, except there is a jump link to the footer. And here is what the footer.php markup looks like:
<?php if(ISMOBILE){ ?> <nav id="footernav"> <?php wp_nav_menu( array('menu' => 'Main' )); ?> </nav> <?php } ?>
In the footer, you are checking to make sure the user is on a mobile device before printing out the navigation.
Moving forward, we will be able to employ this technique in several other areas of the theme. So with all of these techniques and more, how do you decide which one to use?
Ask What’s Best for the Users
As with just about anything in the field of web development (nay, design and development in general), it’s best to ask what’s best for your users. In many cases, that might be whatever takes up the least amount of screen real estate.
However, maybe your users would understand the navigation better if they saw it all laid out in front of them. Maybe your users don’t realize what the “hamburger” icon is. The best thing to do is some research into how your users use your website. Do some A/B testing, or at the very least, get the opinion of friends and family. Ask your users for feedback. As with a lot of things in coding, simple is probably better than clever.
To determine what’s best for your users, ask yourself a few questions:
- From what class/type of devices do my users access the site?
- Are my users there to see what’s on the home page, or do they usually go to a different page?
- What information do I want to present as most important?
- How tech-savvy are my users?
And, as mentioned earlier, give them some options and see what works out best.