Photo of Nathan Shubert-Harbison Nathan Shubert-Harbison

Main content

Content Folding With harvey.js and jQuery

There was a time when designing a website implicitly meant creating a 640px-wide design. Eventually, 960px became the norm, and a bounty of grid systems based on that screen width sprung forth.

In those days, nearly all internet users were browsing on desktop computers—at a desk, using monitors of predictable resolutions. Since then something changed: the smartphone was created and the internet became mobile. What was once an activity confined to an office became something you do on the bus, while walking your dog, and during commercial breaks. This shift fundamentally changed our relationship with the internet, and the way we create websites.

Since smartphones and tablets come in all shapes and sizes, we can no longer assume the screen size of our website visitors. Various approaches have emerged to deal with this, and responsive design is one of them.

The principal advantage of responsive design is that, rather then relying on a separate theme for mobile users, it allows you to create a single theme that adapts to the device you’re using. This approach relies on fluid layouts, media queries, and other techniques.

A single, adaptable theme has huge advantages. For users it alleviates the frustration many of visiting a mobile version that lacks the depth of content of its full counterpart.

Content folding offers more control than media queries when adjusting websites to various screen resolutions.

With a responsive theme, all of the content and features are still there, they’ve just been moved around, and condensed into a single column, so the user doesn’t have to zoom in and out to find what they’re looking for.

There is, however, one disadvantage to the way responsive sites are typically built. We address the problem with a technique called content folding.

What is content folding?

A typical website layout features a main column for your content, and a narrow sidebar column, as illustrated below:

Typical website layout with main column and sidebar

The sidebar can contain anything from parenthetical information to secondary navigation. In a typical responsive layout, once the the screen is too small for two columns, both columns become full width, stacked one on top of the other.

Responsive layout with sidebar and main columns stacked

The problem with this kind of layout is that the sidebar often contains information contextually relevant to the main column. If the sidebar gets pushed underneath the main column, that contextual relationship is damaged. The problem is even greater if the sidebar contains sub-navigation. If that’s the case, the user might need to scroll past an entire blog post to find the navigation.

Sidebars also often contain advertisements. If the entire sidebar, advertisements and all, were pushed underneath the main content column, advertisements would receive far fewer impressions, to the dismay of advertisers.

These issues can be addressed with content folding. Content folding offers more control than media queries when adjusting websites to various screen resolutions. Whereas media queries only allow us to adjust how an element is displayed on the page based on screen dimension, content folding allows us to move elements in the DOM, and change where they sit on the page. Instead of just stacking columns on top of each other, content folding allows us to integrate the content.

Illustration of content folding integrating content

Here’s an example from a site we built with a secondary navigation in the sidebar:

Screenshot of website with secondary navigation in sidebar

If we put the sidebar after the main column for smaller screens, you’d have to scroll past the content to get to it. Instead, we used content folding to move the secondary navigation underneath the main navigation.

Screenshot of website using content folding

In this example, the sidebar contains information that adds context to what you’re reading—in this case the author’s information. Instead of letting that drop underneath the post, we’ve moved the author info into the main column.

Screenshot of layout with important info in the sidebar
Screenshot of same layout on a smartphone with sidebar info folded

Content folding with JavaScript

Although CSS regions are in development, they’re quite a ways off. In the meantime, we use JavaScript to execute content folding. Our script will need to do a few things:

  • Run JavaScript at specific screen dimensions
  • Use the same screen dimensions as our CSS media query breakpoints. This allows us to change CSS and JavaScript concurrently.
  • Run this JavaScript on page load and on resize, but only execute the desired JavaScript once. We want JavaScript to fire when we enter a breakpoint, but we don’t want it firing off continuously as we resize the browser.

Harvey.js

When I first started doing content folding I was using Modernizr to evaluate media queries until Doug Avery from Viget introduced me to harvey.js—a jQuery plugin built by Harvest designed specifically for media query-specific JavaScript. Harvey.js is lightweight and fits all the requirements outlined above.

Harvey.js can be downloaded on GitHub, and more information can be found on the Harvest website.

How harvey.js works

Harvey.js is very simple in use. You provide harvey.js with a CSS media query, and it fires designated functions at various points. They are:

  • When your media query is true (referred to as on)
  • When your media query is fale (referred to as off)
  • When your media query becomes true for the first time (referred to as setup)

Syntax

Harvey.attach('screen and (min-width:600px) and (max-width:900px)', {
    setup: setup_function,
    on: on_function,
    off: off_function
});

Moving DOM elements with jQuery

Once we know how harvey.js works, and that it can call functions based on the evaluation of a media query, we need to create some functions that move elements around the page. Fortunately this is a simple process with jQuery.

Let’s say we wanted to move a sub-navigation from the sidebar to the header underneath the main nav for small screens.

First we create a variable containing a jQuery resource of the element we want to move around:

var secondaryNav = $('#sidebar .secondary_nav');

Then, using jQuery’s .append() and .prepend() methods, we can easily move a cached element around the DOM.

The following function moves the secondary nav into the header under the primary navigation:

function foldSecondaryNavIntoHeader() {
    $("#masthead").append(secondaryNav);
}

The previous function would get called when a media query for a narrow screen evaluates as true. If that changed—either by resizing the browser or changing the device’s orientation—we’d want to move the secondary nav back to the sidebar. This is achieved with the following function:

function unfoldSecondaryNavIntoSidebar() {
    $("#sidebar").prepend(secondaryNav);
}

Calling these functions with harvey.js would be done like this:

Harvey.attach('screen and (min-width:600px) and (max-width:900px)', {
    on: foldSecondaryNavIntoHeader,
    off: unfoldSecondaryNavIntoSidebar
});

Calling multiple functions with harvey.js

You can call multiple functions at a breakpoint like this:

Harvey.attach('screen and (min-width:600px) and (max-width:900px)', {
    setup: setupMidsizeBreakpoint,
    on: function() {
        doFirstThing();
        doSecondThing();
    },
    off: function() {
        undoFirstThing();
        undoSecondThing();
    }
});

Content folding going forward

Clearly content folding is a powerful technique, and allows you to create responsive sites that are more tailored to various screen sizes than would be possible with media queries alone. Once CSS regions gain support we’ll be able to do content folding with CSS alone, but in the meantime, harvey.js is a fantastic way to make it happen today.

Code demo: I have a code demo of content folding on GitHub.

This post was originally written for the Domain7 blog.