Cloud Four Blog

Technical notes, War stories and anecdotes

Don’t use <picture> (most of the time)

Browser support for the picture specification is landing and as Marcos Cáceres said, it is time to “go forth and <picture> all the things!

Except you shouldn’t. You shouldn’t <picture> all the things.

But you should start using picture now for responsive images. No reason to wait.

Confused? You’re not alone.

<picture> vs. picture

Standards are developed in non-linear fashion. Ideas evolve and merge. And often at the end of a lengthy process, you look back and wonder how you got here.

And in this case, where we ended up is with a specification called ‘picture’ that contains much more than the <picture> element. The picture specification includes srcset and sizes and you can use those attributes without using the <picture> element.

Knowing which use case you’re solving tells you what solution you need

One of the earliest pieces of work that the Responsive Images Community Group undertook was defining the use cases for responsive images.

You don’t need to know all of the use cases, but you do need to know the difference between the two most common use cases in order to know which part of the picture specification will solve your problems. The two common use cases are:

  • Resolution switching — In the resolution switching use case, we need to select a different source of the same image because we need a different resolution for any number of reasons. These reasons include the image being used at a different size based on the size of the screen, the pixel density of the screen, or to avoid downloading unnecessarily large images.1

  • Art direction — In the art direction use case, there is some reason why we need to modify the content of an image under certain conditions. Maybe we need to crop the image differently on small screens. Or perhaps we’re working with a hero image that contains text and simply providing a smaller version of the image won’t work because the text will be unreadable.

Basically, if you could resize an image without making any other changes, and have a new source that solves your responsive images needs, then you’re talking about the resolution switching use case. If you need to change anything other than resolution, you’re talking about art direction.2

For most responsive images, you won’t need the <picture> element

Unless you’re solving for art direction, you don’t need to use the <picture> element. In fact, you’re likely doing your users a disservice by using the <picture> element.

The picture specification supports syntax that can be used without the <picture> element. An example syntax, borrow from Yoav Weiss’ excellent article Native Responsive Images, might look like this:

<img src="cat_500px.jpg"
    srcset="cat_750px.jpg 1.5x, cat_1000px.jpg 2x"
    width="500px" alt="lolcat">

Which will provide the browser with different options for display density. Or in a more complex example:

<img sizes="(max-width: 30em) 100vw,
            (max-width: 50em) 50vw,
            calc(33vw - 100px)"
    srcset="swing-200.jpg 200w,
            swing-400.jpg 400w,
            swing-800.jpg 800w,
            swing-1600.jpg 1600w"
    src="swing-400.jpg" alt="Kettlebell Swing">

There is a lot to digest in those examples, and unfortunately, I don’t have the space to cover the syntax here. Instead, I recommend reading Yoav’s article or one of the additional resources listed below if you want to understand the details.3

When you use the srcset and sizes attributes on an <img> element, you are providing information that the browser can use to make an informed decision about what image is appropriate for the user based on a bunch of factors that you are unaware of.

As a web designer or developer, you have no way of knowing how much bandwidth the user currently has or if they’ve declared some sort of preference for the density of images they want. If we provide browsers with information via srcset and sizes then browsers can make smarter decisions about the appropriate image source.

In fact, I hope that browser makers compete on how they handle srcset and sizes by developing new user settings or smarter algorithms to help them pick the right images to download.

But none of that is possible when you use the <picture> element and its media attributes:

<picture>
    <source media="(min-width: 45em)" srcset="large.jpg">
    <source media="(min-width: 32em)" srcset="med.jpg">
    <img src="small.jpg" alt="The president giving an award.">
</picture>

When you specify the media queries for sources, you are providing rules to the browser that it must follow. The browser has no discretion to make smart decisions about what to download based on user preference, network, etc.

You should use the power to dictate what image gets downloaded sparingly. In fact, you should only use it when you’re solving for art direction, not for resolution switching.

For the majority of the images on the web, <picture> is the wrong solution

Last year, Yoav tried to figure out what percentage of responsive images fell under the art direction use case. The answer: 25%.

Responsive design is still early so we may find that the percentage changes, but it is unlikely that we’ll ever reach a point where the number of art directed responsive images out-numbers the number of resolution switching ones.

Therefore, for most responsive images, the <picture> element is the wrong solution. You should be using <img> with srcset and sizes.

The future of the web depends on us getting this right

Getting this right matters a great deal to the future of the web. We’ve seen in the past what happens when web developers create a large installed base of suboptimal web pages. We end up with browsers adopting other browser’s css prefixes or media types such as mobile and TV ignored by all mobile phones and TVs.

If we create thousands of web pages that use the <picture> element for resolution switching, we doom ourselves to having to specify every single image needed instead of letting the computers—the browsers—do what they do best and automatically find the right image based on a multitude of variables.

Worse, we doom our users to a future where they are unable to take advantage of whatever browser advances come because we’ve taken the browser’s discretion away and dictated what image should be downloaded.

Perhaps we need to stop referring to the picture specification

A lot of this confusion comes from the fact that we have a specification that ended up with picture in the title even though the specification covers more than just picture.

For those who have been heavily involved in the development of a solution for responsive images, picture is a nice shorthand. That’s why you see that even it referred to as <picture> in Chrome Status and Modern IE Status.

Using picture as a shorthand it creates confusion when talking to people who are just now looking to implement responsive images. I asked the Responsive Images Community how they’ve been handling this confusion.

Bruce Lawson says:

I tend to refer to “picture and friends” or, generically, “responsive images”

And Odin Hørthe Omdal adds:

I always talk about responsive images, and I think I probably say the respimg specification.

So I’m going to attempt to do the same. I’m going to break myself of the habit of referring to the picture specification and instead refer to responsive images specification even if that isn’t technically the name of the specification. I think people will understand what I mean, and it will help ensure more people understand that it isn’t all about <picture>.

Simple guidelines for using the responsive images specification

To summarize:

  • The picture specification contains more than just the <picture> element. Think of it as the responsive images specification.
  • For most responsive images, you shouldn’t use the <picture> element. You should use srcset and/or sizes.
  • The way to know when to use the <picture> element is based on the use case you’re trying to solve.
  • If you’re solving for the art direction use case, use the <picture> element. Anything else, you should stick to srcset and sizes.
  • Getting this right early—before we have thousands of pages using <picture> incorrectly—is critical for the future of the web.

And with that, I will amend what Marcos wrote to say, “Go forth and make all your images responsive!”


  1. In the responsive images use case document, resolution switching is described with three different examples: Resolution-based selection, Viewport-based selection and Device-pixel-ratio-based selection.
    And yes, they are all different reasons why you want to select a different resolution source, but they all involve resolution switching which is why I’m lumping them together.
  2. You may find this article I wrote on A Framework for Discussing Responsive Images to be a good high-level overview of the use cases.

  3. Some additional articles to help you understand the full features of the picture specification: HTML5 Rocks: Built-in Browser Support for Responsive Images, Srcset and sizes and Responsive Images Done Right: A Guide To <picture> And srcset by Eric Portis.

Two pretty-good techniques for styling tricky form elements

Confession time: For most of my career, I despised form elements. Checkboxes, radios, selects and file inputs seemed to gleefully defy what little control I expected from an HTML element. Their penchant for idiosyncracy drove me to almost as much hair-pulling and teeth-gnashing as IE6 or web-safe fonts.

These days, my frustration with form elements has quieted. Partly that’s because browsers and development tools are so much better. But more significantly, I now understand the benefits of surrendering some control to the operating system. As devices continue to accept a greater and greater variety of input methods (keyboard, mouse, touch, voice, gesture, remote, etc.) while browsers adopt an astounding variety of new input types , it’s a gift for vendors to provide default experiences consistent with the user’s expectations of the platform.

So I no longer strive for “pixel perfection” when styling form elements. I don’t need absolute control. All I want is something easy to tap that feels intentional.

When the browser defaults don’t get me there, here are my go-to workarounds.

Checkboxes and Radios: Styled Sibling

This technique works in any browser that supports CSS3 selectors (basically IE9+). If you read Radio-Controlled Web Design a few weeks ago, this should feel familiar. Let’s start with a checkbox example.

We’ll need a few HTML elements:

  • The <input> itself.
  • A dummy element to style (right next to the <input>).
  • A containing <label> that passes click events to the aforementioned <input>.

I like to wrap the <input> and dummy elements in a container to keep everything nice and tidy, but strictly speaking it isn’t required. Here’s what that markup might look like:

<label>
  <span class="checkbox">
    <input type="checkbox">
    <span class="checkbox-value" aria-hidden="true"></span>
  </span>
  Set phasers to stun
</label>

We’re now free to visually hide the checkbox, styling .checkbox-value however we like:

/* hide the "real" checkbox visually */
.checkbox input {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}
 
/* style the "fake" checkbox */
.checkbox-value {
  /* default/unchecked styles */
}
input:checked + .checkbox-value {
  /* checked styles */
}

When the user clicks the label, the click is passed along to the <input>, which toggles the state of :checked, which affects the appearance of .checkbox-value.

Here’s an example that styles the checkbox like an iOS-style switch:

See the Pen Styled checkbox by Tyler Sticka (@tylersticka) on CodePen.

Here’s the same idea applied to radio buttons with a slightly more conventional design (incorporating a base64-encoded SVG checkmark):

See the Pen Styled radios by Tyler Sticka (@tylersticka) on CodePen.

This technique has a few drawbacks. It requires some extra markup. It won’t work in IE8 or earlier without a fallback. It could probably use another pass for accessibility. But compared to most of the JavaScript solutions I’ve tried, this feels straightforward, consistent and predictable.

Selects and File Inputs: Transparent Overlay + JavaScript

For more complex elements like <select> and <input type="file">, we can’t get by on CSS alone (though it gets us further than one might expect).

Our markup is similar to the previous set of checkbox/radio examples, except we won’t need a <label> for click events:

<div class="select">
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
  </select>
  <span class="select-value" aria-hidden="true"></span>
</div>

Instead of hiding the <select> entirely, we want to position it over the rest of our element, allowing it to intercept click events and correctly position any dropdown it may display. Because this technique relies on JavaScript, we’ll qualify some of our selectors with .js (since you’re probably already using Modernizr).

.js .select {
  position: relative;
  /* default styles */
}
.js .select:hover {
  /* hover styles */
}
.js .select.focus {
  /* focus styles */
}
 
/* nicer default styles for "real" <select> */
.select select {
  cursor: pointer;
  display: block;
  width: 100%;
}
/* hide and overlay when JavaScript is enabled */
.js .select select {
  left: 0;
  height: 100%;
  min-height: 100%;
  min-width: 100%;
  opacity: 0;
  position: absolute;
  top: 0;
}

Already, this “works.” Options will display on click. But there are some problems. The value doesn’t update. There are no hover or focus styles. That’s where JavaScript comes in!

(Although I’ve chosen to write this in jQuery for the sake of readability, remember: You Might Not Need jQuery!)

// For each .select element
$('.select').each(function(){
  // Save some elements as variables
  var $element = $(this);
  var $select = $element.find('select');
  var $value = $element.find('.select-value');
  // Bind event handlers to <select>
  $select.on({
    // On change or keyup, update the value text
    'change keyup': function () {
      $value.text($select.val());
    },
    // On focus, add the focus class
    'focus': function () {
      $element.addClass('focus');
    },
    // On blur, remove the focus class
    'blur': function () {
      $element.removeClass('focus');
    }
  });
  // Trigger the change event so the value
  // is current
  $select.trigger('change');
});

Here’s how all of that comes together:

See the Pen Styled select by Tyler Sticka (@tylersticka) on CodePen.

With some tweaks, the same basic technique can also work for file inputs (assuming experimental WebKit/Blink features aren’t your thing):

See the Pen Styled file input by Tyler Sticka (@tylersticka) on CodePen.

This idea isn’t new. Peter-Paul Koch wrote about it quite a while back. Yet I rarely see it in use outside of a few large mobile frameworks. I’m honestly not sure why.

…and beyond?

What do all of these examples have in common? They don’t mess with the form element too much! By worrying less about customizing behavior and more on simply triggering it, we can indulge some of our designerly impulses without discarding all a given platform has to offer.

Consistency and functionality… no hair-pulling or teeth-gnashing required!

Update: September 8, 2014

A reader pointed out that the select example wasn’t responding to keyboard input in Firefox. I discovered that Firefox doesn’t fire the change event for selects like other browsers do, so I’ve updated the demo and example code so that it binds to both change and keyup.

I also learned that Firefox doesn’t show the full dropdown on any keypress, but this seems to be true of unstyled <select> elements as well. I encourage developers to use these examples as a starting point, and to augment usability shortcomings on a case-by-case basis if the default browser behavior isn’t cutting it.

Fantastic intro to new srcset and sizes

I normally don’t write a post simply to link to another article, but if you’ve enjoyed the things I’ve written about responsive images, you really should read what Eric Portis wrote about Srcset and Sizes.

Eric describes the logic behind srcset and sizes, how they are part of the new picture proposed standard, and how to use them.

Easy. Peas.

Common Patterns in Styleguides, Boilerplates and Pattern Libraries

It’s hard to believe it’s been almost three years since the publication of Ethan Marcotte’s seminal Responsive Web Design article on A List Apart.  The ideas and techniques described therein blew our minds while forcing us to drastically reconsider our design processes. Even today, the struggle continues to determine which design deliverables make sense in a post-PSD era.

Personally, I dig Dave Rupert’s idea of “Tiny Bootstraps, for Every Client”:

Responsive deliverables should look a lot like fully-functioning Twitter Bootstrap-style systems custom tailored for your clients’ needs. These living code samples are self-documenting style guides that extend to accommodate a client’s needs as well as the needs of the ever-evolving multi-device web.

The whole post is great, and it got me thinking… along with solid content strategy, design and engineering processes, what steps can we take to insure our “tiny bootstraps” are comprehensive enough to remain relevant and useful long after launch?

Cue Jason with a cool idea: We could document patterns in existing frameworks. A list of what’s typically included might serve as a good starting point, something to measure our client deliverables against to make sure we haven’t overlooked anything obvious.

In which I willingly make a spreadsheet

 I combed through a (non-exhaustive) collection of suitably broad or noteworthy links from Anna Debenham‘s list of front end styleguides and pattern libraries, recording instances of observed patterns and adding new ones as necessary. I skipped over anything that seemed too idiosyncratic, and grouped elements of similar intent even if their description or implementation differed.

The results are contained in this handy Google Doc.

Lessons learned

I found this to be a worthwhile exercise. It helped me wrap my head around the elastic scope of a “tiny bootstrap.”

I thought there’d be more overlap between frameworks than there is. I recorded over 160 distinct patterns, none of them ubiquitous. Some came pretty close, especially headings 2 through 4, typographic elements and pre-HTML5 form elements. No single framework included even half of the total recorded patterns (Bootstrap had the most).

Sometimes the most infrequent elements surprised me with how obvious they seemed in retrospect. For example, color guides and font stacks only occur in a couple of places.

The thought of maintaining the document indefinitely makes me queasy, but I’ve already started referring to it frequently. I’d love to know if anyone finds it as interesting or useful as I have.

Android Browser Countdown

Android’s poor browser has been the thorn in side of mobile web developers for quite some time. Dion Almaer once said that “Android WebKit is the closest thing to being the IE6 of mobile development”.

I agree. Back in 2011, I wrote that Google needed to step up. Thankfully, they have. Chrome for Mobile is a great browser.

But Chrome for Mobile is still a small percentage of what people on Android devices are using. A lot of this has to do with the fact that older versions of Android that cannot run Chrome still account for 44.1% of Android’s installed base.

Pie chart of Android versions. Versions below 4.0 are 44.1%

Last month at the Breaking Development conference, many of the speakers talked about large installed base of Android browsers as being an impediment to pushing the web forward on mobile. The discussion reminded me of the efforts that the web community undertook to convince users to move off of IE6.

Web developers started encouraging users to upgrade to a newer version. Microsoft helped out by creating the IE6 Countdown web site which helped web developers figure out when IE6’s market share had gotten low enough that they no longer had to worry about it.

Microsoft and others created banners and warnings that encouraged people to install newer, more standards-compliant browsers.

Microsoft supplied warning bar for an out of date version of IE

I’ve thought a few times about how we should encourage Android users to upgrade their browsers, but in this case, there is no way for them to update to a new version of the Android browser and they can’t install Chrome on any device not running Android 4.x.

But while discussing this at Breaking Development, it was pointed out to me that even if people cannot update their browser to Chrome, many do have other options. They can install Opera Mobile or Firefox.

Maybe it is time to change our mindset towards the Android 2.x Browsers and instead of working around its many limitations, perhaps we should actively encourage people to switch to a better browser.

What do you think?