An Event Apart: Responsive and Responsible

by May 21, 2013

In his presentation at An Event Apart in San Diego 2013 Scott Jehl outlined a number of ways to build responsive Web sites that take performance in account. Here's my notes from his talk: Responsive and Responsible.

  • We need to build Web products to be universally accessible. This includes a lot more than just people with disabilities – it includes slow network connections, less capable devices, and more.
  • Defensive design and progressive enhancement are a safety net against Murphy's Law. We can't think and code in absolutes.
  • Responsive design is just part of building a responsible design. We need to consider a number of factors beyond the layout: performance, behavior, accessibility, and costs.
  • Most of poor performance is our fault: the average page in 2013 weighs 1.4MB. The average load time of a top 2000 site is 6 to 10 seconds.
  • Good performance is good design. Fast loading Websites make people happy.
  • Webpagetest.org and Web Inspectors in the browser provide a way for you to measure performance and see what's slowing pages down.
  • 86% of responsive designs send the same assets to all devices.

Content Parity, Optimized Experience

  • We want to deliver content based on our user’s needs. Only a few years ago we were locked into normalizing things across a number of browsers. Today the diversity of devices makes this idea seem ridiculous. Instead we want to optimize for different devices.
  • Content parity does not mean every experience is identical. Every browser that comes to our Web site is unique. We need to code in a way that doesn’t presume too much about: viewport size, orientation, font size, settings, preferences, and input modes.
  • Being responsive from a layout perspective doesn’t preclude being responsive form a performance perspective.
  • Using em-based breakpoints in your media queries means you are not dependent on device sizes and allow users to adjust font size without breaking layout.

Delivering Content

  • To load content from a Website, a client makes a request, DNS sends it to the right host, and the host replies with the requested assets. The DNS server finds the right IP address to serve, then goes to a host to get content.
  • On mobile devices, we go to a cell tower first, then to a DNS, then a host to get content. The connection to the tower takes two seconds and is totally out of our hands. That delay is unique to mobile and only happens once. Then we can send files back and forth after the initial connection is made.
  • From there we load HTML and any referenced files when all blocking files (that impact rendering) have been received. Be careful of what you include in blocking requests.
  • After 8 seconds, the carrier will cut off a connection so we want to load as much as possible when that initial connection is open.
  • Every http request we make is a bit of a gamble -it can fail. So we don’t want to gamble too much with many requests -especially if they are blocking.

Delivering HTML

  • Tiered delivery: if a piece of content is already accessible somewhere else (through a link on the page), you might consider loading it lazily.
  • For example: home pages are navigation tools. They mostly include links to other parts of the site.These kinds of pages are prime for deferred loading.
  • In the initial load, we could just include the critical links in the source then use Javascript to load additional content (like samples of what’s behind that link) after the initial page downloads.
  • We can enhance the content itself using a technique called Ajax-include. We start with a simple URL and add a data attribute that references an HTML fragment to the link’s mark-up. When Javascript is executed, the link will be replaced with a full set of content using Ajax.
  • To do this, consider using a data attribute on a link like “data-after”.
  • You could take this deferred loading further and only show the additional content if a certain media query condition is met.

Delivering CSS

  • CSS is a blocking element: browsers wait until it is all loaded before displaying a page. This prevents un-styled content from showing up.
  • Mobile-first media queries: start with CSS that is wide open. Assume no media queries are present. Then adjust using min-width media queries.
  • Mobile-first media queries deliver a broadly usable default. These initial styles go to all browsers but it sometimes you might want to use a "@media only all" qualifier to target all browsers that support media queries. This is a good way to qualify more advanced styles.
  • Start with simple design and typography in the basic experience, then enhance upward.
  • Enhancement qualifiers broaden access and help to simplify QA processes.
  • But with this approach, we are sending all our CSS files to all browsers even if they’ll never use them.
  • Every browser downloads every CSS asset today –whether it needs it or not. While we want style sheets to be there when we need them, we don’t necessarily want them to be blocking page rendering.
  • Webkit does a little better, it loads media queries that apply and renders those on screen and does not block on CSS that is not currently applicable. However it still downloads all CSS files regardless of whether they can be used on the device or not.
  • The best approach for CSS is still to combine all your CSS in one file. But minify and gzip it. CSS compresses well. GZIP finds repeating segments and reduces CSS file size substantially.

Delivering Images

  • Images are 66% of file size on Web pages.
  • Images don’t block page rendering but they can negatively impact page size and data plans.
  • Background images can be managed with media query cascades to only be loaded when needed. Foreground images are another story.
  • Compressive images: the quality of a jpg influences its files size more than its pixel dimensions.
  • Scaling an image doesn't solve all the use cases you might want. Like the art-direction use case.
  • Responsive images: two proposals have made their way into the standards process: picture and srcset.
  • The picture element works like the video element in HTML. It has a number of media query-qualified images to load based on what each browser can support and a standard image for fallback when none of those attributes are true.
  • Srcset is an attribute that you add to an image element. Its very good at managing pixel densities through attributes like 2x, 3x. The browser has the last say on which image to load.
  • Picturefill is a Javascript polyfill that brings similar support to a DIV-based solution. This prevents pre-fetching images that are not needed.
  • Should we load retina images for devices that can use them or should we give people a choice of what kind of image they want? After all, serving retina images by default really increases download size.
  • The picturefill solution can be used to load a standard definition image by default and then give people the option to load a high-resolution image if they choose on their retina device.
  • Managing images for all the different resolutions is getting harder and harder. Instead of using raster images for icons and background, we could use vector art using SVG.
  • SVG is text it compresses very well because it is just mark-up. Referencing SVG inline is relatively easy. Browsers that support SVG load it easily but those that don’t can be supported with an onerror attribute to load a fallback image.
  • You can also specify images as background images or as data URLs that don't require an additional http request.
  • Grunticon is a tool that listens to a directory of SVG files, updates a CSS file that encodes all those files as data URIs as CSS classes, which can then be concatenated with other CSS files.

Delivering Javascript

  • Javascript is the second largest part of our pages and it blocks page rendering until loaded.
  • Start by loading the smallest amount of Javascript you can. Use it to determine what to load next. Initial Javascript: load feature tests, essential polyfills, asset loader, and a script loader.
  • Yepnope is a very lightweight loader that allows you to determine when to serve Javascript.
  • If a device is qualified, you can add the Javascript you’ll need everywhere and specific files based on what each device can use. How to determine what Javascript to load: broad qualification, browser features, device/environmental conditions, or template types.
  • You can load some CSS with Javascript as long as it is not required for default presentation. Additional fonts or background images are good candidates for Javascript loaded CSS.
  • Third party widgets (to embed on your site) should be loaded asynchronously. But support for async is not perfect as it is only supported in Internet Explorer 10+
  • Surefire DOM element insertion by Paul Irish is a great article about loading Javascript effectively.
  • Defend the critical path to loading key content for your pages.
  • We have the tools to create rich experience without excluding people. But we need to work responsibly to do so.