Video

Want to see the full-length video right now for free?

Notes

Responsive design is a critical approach to making sure your content is useful and readable on the increasingly large array of device sizes in use today. Tune in as Chris and Ryan discuss the ins and outs of responsive design, sharing the techniques, workflows, and thinking we use here at thoughtbot.

What is Responsive Design

"Responsive design" is an approach to web design where the content and layout adapts to the various sizes of the viewport, most notably to ensure the content is displayed in a useful manner across a variety of devices such as a large screen desktop monitor, a medium sized tablet, a mobile device, and everything in between.

A great example of responsive design is the Boston Globe site. If you open that site in a desktop browser and begin to decrease the width of the browser window, you'll notice that all of the content proportionally resizes for a bit, then at a certain point there is a distinct change as it transitions from a three-column layout to a two-column layout. This combination of proportional sizing and discreet reflowing of content for specific width ranges comprise the core of responsive design.

Alternative Mobile Sites

Core to the idea of responsive design is the idea of always serving the same content, and then using CSS to adapt the content and present in the most useful and readable way for the given device width and related constraints.

We're big believers in this approach for the vast majority of content on the web, but to briefly contrast, at the other end of the spectrum we have an approach where the server will either redirect the user, or at least respond with entirely different content. Often this content is served from a mobile specific subdomain, for instance m.example.com, sometimes referred to as "m-dots". This is typically done by user-agent sniffing, but this is a practice that is generally recommended against.

Further, this practice of splitting traffic and server entirely different content very often leads to a subpar experience. Redirects can lose the specific resource and dump you on a mobile index, the content is often truncated preventing you from finding the needed information, and links are now device specific. Additionally, this practice likely leads to at least double the work as you now need to maintain two separate versions of your site.

GitHub's Mobile Views

One counter-example to the recommendation to avoid mobile specific views is GitHub's mobile views. GitHub did a great job of maintaining the URL, providing a trimmed down versions of the page specifically targeted at mobile, and provides a link in the footer to explicitly request the full desktop version of the page.

Bootstrap and Other Responsive Frameworks

In general we prefer not to use frameworks like Bootstrap (thus we created Bourbon) due to their heavy reliance on non-semantic utility classes. Markup like <p class="text-center"> and <div class="col-xs-8 col-sm-6"> blurs the line between the content and the formatting, effectively locking your design into Bootstrap.

Foundations of Responsive Design

To start, we have a sample CodePen we've built to demonstrate the core ideas of responsive design. The design is a simple header, body and sidebar, then footer. The content is laid out using Slim, but it's worth noting that Slim provides none of the responsive behavior, it just happens to be well suited to defining a sparse document layout.

Flexbox at the Core

Core to our current approach to responsive design is the use of Flexbox. We have an Introduction to Flexbox in a previous episode of the Weekly Iteration which can get you started, but it's worth noting that flexbox does a lot of the heavy lifting and makes much of responsive design drastically easier. Flexbox provides the proportional width half of the responsive design pie by allowing us to easily designate what proportion of the parent container each child element should take up.

Media Queries

[Media queries][] are a syntax for defining discreet transition points, referred to as "break points", where specific styling rules apply. Typically they take a form like:

@media (min-width: 700px) {
  /* This style block will only apply on viewports larger than 700px */
  margin-right: 10px;
  padding: 0;
}

We can implement the rules based on a number of specifics including aspect ratio, height, width, orientation, etc, but by far most common is to define the rules based on either max-width or min-width.

[Media queries]: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries

Combined Example

To provide an example bringing flexbox and media queries together, we have the main content area which wraps the intro and sidebar blocks:

<div class="main-content">
  <div class="intro">
    Content
  </div>
  <div class="sidebar">
    Sidebar
  </div>
</div>

The base styling sets the parent .main-content container to be a flex container, then sets the widths of the intro and sidebar to be 75% and 25%, respectively:

.main-content {
  display: flex;
  margin-bottom: 30px;
}

.intro {
  margin-right: 30px;
  flex: 0.75;
  background-color: #B9C1D6;
}

.sidebar {
  flex: 0.25;
  background-color: #E2E9FA;
}

Already we have a responsive layout based on the flexbox managed proportional widths, but we can go a step further and use a media query to redistribute the space when the width is below 768px:

@media (max-width: 768px) {
  .intro,
  .sidebar {
    flex: 0.5;
  }
}

Here, rather than having the .intro block be three times the size of the sidebar, on these smaller screens we split the space equally to ensure the sidebar doesn't become too small.

Reflowing for Smaller Screens

As we go further, we trip over the next break point at 520px, targeted at mobile devices. These rules kick in for anything below that 520px threshold:

@media (max-width: 520px) {
  .navigation {
    display: none;
  }

  .mobile-menu-icon {
    display: block;
  }
}

The first thing we do is hide the main aviation icons in the header, and instead display the mobile specific navigation menu icon.

Next, we further tap into the power of flexbox to reflow our whole .main-content block:

@media (max-width: 520px) {
  /* ... */

  .main-content {
    flex-direction: column;
  }

  .intro,
  .sidebar {
    flex: 1;
  }
}

Here, we change the flex-direction of the .main-content container to column so the child elements stack vertically (rather than the default row layout), and instruct each of the .intro and .sidebar blocks to now occupy the full width. This is some serious magic, and why we love flexbox.

Using Sass to Clean Up

The initial implementation of this design was done using pure CSS, but in reality we always implement our designs using a compile-to-css language like Sass. Using Sass, we can add clarity and simplify our styling:

@import "bourbon";

$base-spacing: 30px;
$icon-size: 14px;
$light-purple: #E2E9FA;
$dark-purple: #A3AEC5;

// Screen sizes
$small-screen-size: 520px;
$medium-screen-size: 768px;

@mixin below($screen-size) {
  @media only screen and (max-width: $screen-size) {
    @content;
  }
}

Here we've imported our Bourbon library to give us access to its mixins, defined a handful of variables including ones for our break point sizes, and even defined our own mixin for intuitive media queries. In addition, by using Sass we gain access to other features like nesting and calculation functions.

We can see an example of the expressiveness we gain by using Sass with the navigation styling:

.navigation {
  display: flex;

  @include below($small-screen-size) {
    display: none;
  }
}

Here we're able to nest the media query within our style block, keeping things organized, and additionally we're able to take advantage of our width variable and below mixin to write the very clear @include below($small-screen-size) break point declaration. No more confusion about whether it is above or below the specified width!

Testing with the Device Emulator

When implementing a design in a real app, the device emulator in Chrome is a great tool to quickly test out on a number of device widths and orientations. You can check out more in the [Device Emulation portion][] of our Weekly Iteration episode on the Chrome Dev Tools.

While the device emulator is great, it's critical to always test out your site on a real device to fully test it out.

[Device Emulation portion]: https://upcase.com/videos/chrome-dev-tools#device-emulation

Learning More

Ready to dive in and continue learning about responsive design? These links should get you started:

  • [Media Queries on MDN][]
  • CSS Tricks article on [Responsive vs. Adaptive][] design.
  • [Flexbox support][]

[Responsive vs. Adaptive]: https://css-tricks.com/the-difference-between-responsive-and-adaptive-design/ [Media Queries on MDN]: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries [Flexbox support]: http://caniuse.com/#feat=flexbox