Thierry Koblentz

About The Author

Thierry Koblentz Thierry is passionate about Web Design and CSS. He loves the challenge of solving problems and dreaming up original ideas that get him out of bed in the morning and keep him working late at night. He is a front-end engineer at Yahoo! and owns TJK Design, css-101.org and ez-css.org. His twitter handle is @thierrykoblentz.

Device-Agnostic Approach To Responsive Web Design

This is a different take on Responsive Web design. This article discusses how we can better embrace what the Web is about by ignoring the big elephant in the room; that is, how we can rely on media queries and breakpoints without any concern for devices. Let’s start our journey by looking at the online tools such as Responsive Design Testing, Responsive.is, Responsinator and BriCSS....

This is a different take on Responsive Web design. This article discusses how we can better embrace what the Web is about by ignoring the big elephant in the room; that is, how we can rely on media queries and breakpoints without any concern for devices.

The Challenge

Let's start our journey by looking at these online tools:

Those pages let people check websites through a set of pre-built views based on various device sizes or orientations. Bricss goes one step further as it allows you to "customize" viewports by setting any dimensions you want.

Now check the-great-tablet-flood of 2011.

Do you get my drift? Trying to check layouts against specific sets of dimensions is a losing battle. Besides, using existing devices to set break-points is not what I'd call a "future proof" approach, as there is no for standard sizes or ratios.

I don't want to go the "consider it to be harmful" route, but I want to point out that tools like these, or articles promoting a device approach (i.e. Device Diagram for Responsive Design Planning), make people focus on the wrong end of the problem, reinforcing the idea that responsive is all about devices.

To me, it seems more realistic to check our layouts through viewports of arbitrary dimensions and shapes. We don't need anything fancy, we can simply drag the bottom right corner of our favorite desktop browser to enter: "Device Agnostic Mode".

The Goal

The goal is to surface content, to style boxes as columns so they bring sections above the fold. The question is: when should we bring a box "up"?

Content Is King!

If we consider that content is king, then it makes sense to look at it as the corner stone of the solution. In other words, we should set break-points according to content instead of devices.

The Principle

The content of a box dictates its width. It is the minimum width of adjacent containers that create break points (a size at which we can display boxes next to each other).

<p>
    Decisions are made keeping these points in mind:
</p>
<ul>
    <li>
        The width of a box should be as small or as wide as possible without impairing readability.
    </li>

    <li>
        The max-width of a box should take into consideration the importance of following boxes. This is because the wider the box, the wider the viewport must be to reveal subsequent boxes.
    </li>

    <li>
        The goal is <strong>not</strong> to bring everything above the fold (we don't want to fill the viewport with clutter).
    </li>
</ul>

In Practice

<h4>Markup</h4>

<p>For this exercise, we will consider 5 main blocks:</p>
<div class="grid-block" id="header"></div>
<div id="wrapper">
    <div class="grid-block" id="main"></div>
    <div class="grid-block" id="complementary"></div>
    <div class="grid-block" id="aside"></div>
</div>
<div class="grid-block" id="contentinfo"></div>

The wrapper will allow us to:

  • mix percentages and pixels to style boxes on the same row
  • set a maximum width for a group of boxes
<h4>CSS</h4>

<p>
    To build our grid we will rely on <code>display:inline-block</code> mainly for horizontal alignment and inline flow. But note that this choice also gives us an extra edge to play with (more on this later).
</p>
<p>
    Also note that we will override this styling with <code>float</code> to achieve some specific layouts.
</p>
body {
        margin:auto;            /* you'll see why later */
        text-align:center;      /* to center align grid boxes */
        letter-spacing: -0.31em;/* webkit: collapse white-space between units */
        *letter-spacing: normal;/* reset IE < 8 */
        word-spacing: -0.43em;  /* IE < 8 && gecko: collapse white-space between units */
    }
    .grid-block {
        letter-spacing: normal; /* reset */
        word-spacing: normal;   /* reset */
        text-align:left;        /* reset */
        display:inline-block;   /* styling all grid-wrapper as inline blocks */
        vertical-align:top;     /* aligning those boxes at the top */
        *display:inline;        /* IE hack to mimic inline-block */
        zoom:1;                 /* part of the above hack for IE */
        width:100%;             /* boxes would shrink-wrap */
    }

    /**
     * rules below are meant to paint the boxes
     */

    .grid-block {
        height: 150px;
    }
    #header {
        background: #d6cac1;
    }
    #main {
        background: #ad9684;
    }
    #complementary {
        background: #7a6351;
    }
    #aside {
        background: #000000;
    }
    #contentinfo {
        background: #3d3128;
    }

This produces a bunch of rows.

<h4>Content-Driven Process</h4>

<p>
    We define the width of each box according to its content. These values will then be used to set breakpoints. Note that the values below take into consideration a 10px gutter between columns.
</p>

<dl>
    <dt><strong>Header</strong></dt>
    <dd>content: logo, navigation, search box</dd>
    <dd>type: banner</dd>
    <dd>minimum width: n/a</dd>
    <dd>maximum width: n/a</dd>

    <dt><strong>Main</strong></dt>
    <dd>content: diverse (article, blog entry, comments, etc.)</dd>
    <dd>type: main box that holds the meat of the page</dd>
    <dd>minimum width: 420px [<a href="#footnote">1</a>]</dd>
    <dd>maximum width: 550px [<a href="#footnote">1</a>]</dd>

    <dt><strong>Complementary</strong></dt>
    <dd>content: directory entries, tweets, etc.</dd>
    <dd>type: multi-line text box with media</dd>
    <dd>minimum width: 280px</dd>
    <dd>maximum width: 380px</dd>

    <dt><strong>Aside</strong></dt>
    <dd>content: Ads</dd>
    <dd>type: 230px wide images</dd>
    <dd>fixed width: 250px or 490px (2 ads side by side)</dd>

    <dt><strong>Contentinfo</strong></dt>
    <dd>content: resources, blog roll, etc.</dd>
    <dd>type: lists of links</dd>
    <dd>minimum width: 220px</dd>
    <dd>maximum width: 280px</dd>
</dl>

<p>
    The minimum and maximum widths above only come into play when the box is displayed as a column.
</p>

Breakpoints

<p>
    The width of the containers establishes our breakpoints. Breakpoints are viewport's widths at which we decide to display a box as a column (instead of a row).
</p>

How Do We "Pick" Breakpoints?

Until we are able to use something like grid layout, we are pretty much stuck with the HTML flow, and thus should rearrange boxes while respecting their source order. So we go down our list, and based on the minimum width values, we create various combinations. The values below show widths at which we rearrange the layout, styling rows as columns, or changing the width of a specific column.

470px
  • header
  • Main
  • Complementary
  • Aside (250) + Contentinfo (220)
530px
  • header
  • Main
  • Complementary (280) + Aside (250)
  • Contentinfo
700px
  • header
  • Main (420) + Complementary (280)
  • Aside
  • Contentinfo

or:

  • header
  • Main (420) + Complementary (280)
  • Aside + Contentinfo
950px
  • Main (420) + Complementary (280) + Aside (250)
  • Contentinfo
1170px
  • Main (420) + Complementary (280) + Aside (250) + Contentinfo (220)
1190px
  • Main (420) + Complementary (280) + Aside (490)
  • Contentinfo
1410px
  • Head (240) Main (420) + Complementary (280) + Aside (250) + Contentinfo (220)

All of the above are potential breakpoints — each value could be used to create different layouts for the page. But is that something we should automatically do? I think not. At least not without considering these two points:

How close are the breakpoints?
We have 2 that are 20 pixels apart (1170px and 1190px); should we set both of them or should we drop one? I think that above 900px, chances are that desktop users may easily trigger a re-flow in that range, so I would not implement both. In other words, I think it's okay to go with close breakpoints if the values are below 800px — as there is less chance to confuse users when they resize their browser window.

Should we try to create as many columns as we can?
Bringing more ads above the fold may make more sense than bringing up a list of links that you'd generally keep buried in your footer. Also, you may choose to give more breathing room to your main content before bringing up boxes that the user does not really care for.

Getting Ready for Media Queries

For the purpose of this article, we'll use every single one of our breakpoints to create a new layout, which should also demonstrate that it is not necessarily a good idea.

/**
 * 470
 */
@media only screen and (min-width: 470px) and (max-width: 529px) {
    #aside {
        width: 250px;
        float: left;
    }
    #contentinfo {
        display: block;
        width: auto;
        overflow: hidden;
    }
}

/**
 * 530
 */
@media only screen and (min-width: 530px) and (max-width: 699px) {
    #wrapper {
        display:block;
        margin: auto;
        max-width: 550px; /* see comment below */
    }
    #complementary {
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        padding-right: 250px;
        margin-right: -250px;
    }
    #aside {
        width: 250px;
    }
}

/**
 * 700
 */
@media only screen and (min-width: 700px) and (max-width: 949px) {
    #wrapper {
        display:block;
        margin: auto;
        max-width: 830px; /* see comment below */
    }
    #main {
        float: left;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        padding-right: 280px;
        margin-right: -280px;
        height: 300px;
    }
    #aside,
    #complementary {
        float: right;
        width: 280px;
    }
    #contentinfo {
        clear: both;
    }
}

/**
 * 950
 */
@media only screen and (min-width: 950px) and (max-width: 1169px) {
    #wrapper {
        display:block;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        padding-right: 250px;
        margin: auto;
    }
    #main {
        width: 60%;
    }
    #complementary {
        width: 40%;
    }
    #aside {
        width: 250px;
        margin-right: -250px;
    }
}

/**
 * 1170
 */
@media only screen and (min-width: 1170px) and (max-width: 1189px) {

    #main,
    #complementary,
    #aside,
    #contentinfo {
        float: left; /* display:inline here leads to rounding errors */
    }
    #main {
        width: 36%;
    }
    #complementary {
        width: 24%;
    }
    #aside {
        width: 21%;
    }
    #contentinfo {
        width: 19%;
    }
}

/**
 * 1190
 */
@media only screen and (min-width: 1190px) and (max-width: 1409px) {
    #wrapper {
        display:block;
        box-sizing: border-box;
        padding-right: 490px;
        margin: auto;
    }
    #main {
        width: 60%;
    }
    #complementary {
        width: 40%;
    }
    #aside {
        width: 490px;
        margin-right: -490px;
    }
}

/**
 * 1410
 */
@media only screen and (min-width: 1410px) {
    body {
        max-width: 1740px;
    }
    #wrapper {
        float: left;
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        width:100%;
        padding-left: 17%;
        padding-right: 16%;
        margin-right: -16%;
        border-right: solid 250px transparent;
    }
    #header {
        float: left;
        width:17%;
        margin-right: -17%;
    }
    #main {
        width: 60%;
    }
    #complementary {
        width: 40%;
    }
    #aside {
        width: 250px;
        margin-right: -250px;
    }
    #contentinfo {
        width: 16%;
    }
}

For the 530px and 700px breakpoints, there is a design choice to make. Without a max-width, we'd get everything flush, but the main box (#main) would be larger than the maximum width we originally set.

Demo

Please feel free to check out the demo of this technique.

The last thing to do is to create a layout to cater for IE6/7/8, as these browsers will ignore the media queries. To do so, we can use a Conditional Comment:

<!--[if lt IE 9]>
    <style>
    body {
        margin: auto;
        min-width: 850px;
        max-width: 1000px;
        _width: 900px;
    }
    #main {
        width: 55%;
    }
    #complementary {
        width: 25%;
        *margin-right: -1px; /* rounding error */
    }
    #aside {
        width: 20%;
    }
    #contentinfo {
        clear:both;
    }
    </style>
<![endif]-->

Conclusion

Not once in this article I referenced the width of a device, be it an iPad, a Xoom, or something else. Building a "content-aware grid" is a simple matter of choosing the "layout patterns" that you want, based on breakpoints that you set according to page content.

After I sent this piece to Smashing Magazine, I ran into Deciding What Responsive Breakpoints To Use by @Stephen_Greig. So obviously, we are at least two who share the sentiment that relying on devices to create layouts is the wrong approach. But I'm curious to know what everyone else is doing, or even thinking? If we had more people pushing for this, the community could be less device-centric, and could start focusing on content again.

Next Step: Responsive Media

Footnotes

[1] According to Ideal line length for content this box should be styled width a min-width of 25em and a max-width of 33em. So if your base font-size is 16px (as it should be), this translates as 400 pixels and 528 pixels.

(jvb) (il) (vf)


More Articles on

Gridpak: The Responsive Grid Generator

by Erskine Design

This article is the fifth in our new series that introduces the latest, useful and freely available tools and techniques, developed and released by active members of the Web design community. The first article covered PrefixFree; the second introduced Foundation, a responsive framework; the third presented Sisyphus.js, a library for Gmail-like client-side drafts and the fourth shared with us a...

Read more

Techniques For Overcoming Poor CSS Support In Email

by Lynda Elliott

Designing and developing emails can be challenging, especially if you start doing it after years of designing and developing websites. Unlike most Web browsers, email clients have not yet united in support of HTML email standards, resulting in poor CSS support for email. Inconsistent support for images in email clients has thus motivated us to experiment in a code editor and to develop...

Read more

Writing Unit Tests For WordPress Plugins

by Zack Grossbart

When my WordPress plugin had only three users, it didn’t matter much if I broke it. By the time I reached 100,000 downloads, every new update made my palms sweat. My first goal for the WordPress Editorial Calendar was to make it do anything useful. I was new to JavaScript and PHP and didn’t really know what I could pull off. In a few days I had a proof of concept. In a few more I had a...

Read more