Publishers of technology books, eBooks, and videos for creative people

Home > Articles > Web Design & Development > Usability

Making Your WordPress Theme Responsive: Core Features

This chapter looks at some of the core features of WordPress instrumental to a good User Experience, including navigation, images, and widgets.
This chapter is from the book

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

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

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

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

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

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

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

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

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

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.

Peachpit Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from Peachpit and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about Peachpit products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites; develop new products and services; conduct educational research; and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email ask@peachpit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by Adobe Press. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.peachpit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020