Cloud Four Blog

Technical notes, War stories and anecdotes

Responsive Images 101, Part 6: Picture Element

In Parts 3, 4 and 5, we focused on solutions for resolution switching. Now it is time to look at how to solve for art direction.

The picture element—the media attribute in particular—is designed to make art direction easy.

Picture syntax, replicated below

The <picture> element contains a series of <source> child elements followed by the required <img> element. The source elements work similarly to the child sources of the video element.

<picture>
  <source media="(max-width: 500px)" srcset="cat-vertical.jpg">
  <source media="(min-width: 501px)" srcset="cat-horizontal.jpg">
  <img src="cat.jpg" alt="cat">
</picture>

Each source has a required srcset attribute along with optional attributes including media, sizes and type. Both sizes and srcset on a <source> element work exactly the same as they do on an <img> element.

We're going to focus on the media attribute for now.

Media attribute

The value of the media attribute is a media query. Unlike the media condition that the sizes attribute uses, this is the full media query that you've come to know and love.

As the browser looks through the list of source elements, the first source whose media query matches is the one that is used. If no media queries match, then the <img> element is used.

Media attribute is a directive, not a suggestion

Unlike srcset and sizes, when you use the media attribute, you are dictating to the browser which source should be used.

The browser has no discretion to pick a different source. It must use the first <source> element whose media attribute matches the current browser conditions.

This is why the <picture> element with the media attribute is perfect for art direction. In the art direction use case, designers need to ensure that the image used at a particular viewport size is exactly the one they intend otherwise their design may break.

Let's take a look at this in action.

Picture element in the wild

Shopify uses the <picture> element for art direction. Shopify's home page highlights one of their customers, Corrine Anestopoulos, the Founder of Biko Jewellery.

Animation showing changes as Shopify home page viewport shrinks

On narrow screens, the photo of Ms. Anestopoulos is cropped. Because the image is no longer simply being scaled down, this is considered art direction.

The markup that Shopify uses combines the <picture> element with srcset display density descriptors. I've simplified the markup to remove long image paths and included it below:

<picture>
  <source srcset="homepage-person@desktop.png, homepage-person@desktop-2x.png 2x"       
          media="(min-width: 990px)">
  <source srcset="homepage-person@tablet.png, homepage-person@tablet-2x.png 2x" 
          media="(min-width: 750px)">
  <img srcset="homepage-person@mobile.png, homepage-person@mobile-2x.png 2x" 
       alt="Shopify Merchant, Corrine Anestopoulos">
</picture>

Looking at the code in more detail, what we see is the Shopify has three different image breakpoints. The image is a fixed width at each breakpoint—it jumps from size to size instead of flexing between breakpoints.

Because the image is fixed width, srcset display density descriptors make sense. So for each breakpoint, Shopify has defined a 1x and 2x source file. It breaks down like this:

  • <source … media="(min-width: 990px)"> — The largest image size, which Shopify calls desktop, is the first source. The media attribute tells the browser that this source should only be used if the viewport is larger than or equal to 990 pixels wide.

  • <source … media="(min-width: 750px)"> — The second source, the "tablet" image, will be used for viewports larger than or equal to 750 pixels. Because the first source takes effect at 990 pixels and the browser selects the first source that matches, the effective range of the second source is from 750 to 989 pixels.

  • <img> — If there are no matches for the two sources, then the viewport must be smaller than 750 pixels wide. When that is the case, the srcset on the <img> element will be used. This "mobile" image is the cropped image used for small screens.

If the images were flexible instead of fixed width, Shopify could have used <picture> with srcset width descriptors instead of display density descriptors.

One final trick

If you have art direction, you need the picture element. But the writers of the picture specification had one final gift to give us web authors and it's a big one.

Stay tuned for Part 7: Type to learn about an exciting new world of image formats.


Responsive Images 101 Series
  1. Definitions
  2. Img Required
  3. Srcset Display Density
  4. Srcset Width Descriptors
  5. Sizes
  6. Picture Element
  7. Type
  8. CSS Responsive Images
  9. Image breakpoints

Introducing Leveller: Please Avoid Using It

This happens to me over and over: I have a multi-column grid of tiles, each with varying heights. This means the bottom of certain rows can appear jagged and difficult to scan visually:

See the Pen Leveller: Before by Tyler Sticka (@tylersticka) on CodePen.

Ideally, I’d use flexbox to solve that problem with a shockingly small amount of CSS (especially if you use Autoprefixer). Seriously, look how well that works:

See the Pen Leveller: Flexbox Alternative by Tyler Sticka (@tylersticka) on CodePen.

Sadly, that solution rarely makes it into production on the projects I’ve worked on. Sometimes browser support is the culprit. Other times we’ve inherited particularly uncooperative grid patterns (either from an existing project, or an overzealous framework).

Over the last few years, I wrote and re-wrote project-specific, bespoke JavaScript to solve this problem. I’ve finally accepted that it isn’t going away, at least not as quickly as I’d like it to.

So I’ve written a jQuery plugin for equalizing element heights. It’s called Leveller:

See the Pen Leveller: After by Tyler Sticka (@tylersticka) on CodePen.

Don’t use Leveller if you can help it. Flexbox is way more appropriate. If you only need to adjust min-height properties, Equalizer is a leaner, dependency-free solution.

But if all else fails, Leveller is available now on GitHub (and also via npm). Godspeed!

Responsive Field Day Portland!

For the last two years, I’ve devoured the podcasts from Responsive Day Out—the conference that Jeremy Keith and Clearleft put on across the pond in Brighton.

I’ve encouraged anyone who would listen to subscribe to the podcast. It is my favorite conference that I’ve never been to.

That’s why I’m so thrilled to announce that we’re bringing the Responsive Day Out format to Portland!

Responsive Field Day

We’re calling it Responsive Field Day. It is a one-day conference on responsive design. It will take place on September 25 at Revolution Hall.

We plan to continue the spirit of the Brighton event where Jeremy famously said that “every expense has been spared.” So you can be certain the event will be affordable and inclusive.

Lyza, Aileen and I are traveling to Brighton for Responsive Day Out 3: The Final Breakpoint to watch the masters and learn how to make Responsive Field Day a success.

We’ve already got some fantastic speakers lined up. We’re not ready to announce the lineup yet though, so you’ll have to trust us when we say, “OMG! OMG! I can’t believe they said yes!

So mark September 25th on your calendar and start planning your trip to Portland. Sign up for email or follow us on Twitter to receive updates when the speakers are announced and tickets go on sale.

Finally, thanks so much to Jeremy and Clearleft for inspiring us and sharing what they’ve learned.

The End of Mobile Portland

In December 2007, Lyza, Aileen, John and I decided to start Mobile Portland so we would have place to talk about mobile.

After eight years, Mobile Portland is coming to an end. Tonight is the final meeting.

Over the years we’ve had some amazing speakers and topics. I’m proud of the quality of the talks and the community we built.

We also inadvertently started a worldwide open device lab movement. It’s been amazing to see device labs spread and know they started in Portland.

I’d like to thank everyone who attended a meeting and those who helped out in any way. Every small contribution lifted a huge burden off the shoulders of frantic organizers.

I want to extend a special thank you to my co-founders at Cloud Four for helping get Mobile Portland off the ground and funding it; Matt Gifford for organizing so many meetings; Seth Shikora for recording nearly every meeting we’ve held; and to Elia Freedman, Dylan Boyd and Rob Mills for being the best board members I could have asked for.

Tonight’s meeting

But before Mobile Portland rides off into the sunset, we have one final meeting tonight, and it is going to be the best one yet!

I can’t think of a better speaker and a more fitting topic than Josh Clark talking about Magical UX and the Internet of Things. This is the next frontier of technology and mobile plays a bit part in it.

This will also be our largest meeting ever. We’ve had to create a waitlist for the first time so if you’ve already RSVP’d and are unable to make it tonight, please update your RSVP so people on the waitlist can attend.

What’s next?

Since we announced the end of Mobile Portland, people keep asking me two questions. First, “Why end Mobile Portland when there is still a lot of interest?”

Because eight years is a long time to do anything and instead of the group gradually winding down and losing relevance, we made the decision to go out on top.

The second, inevitable question is, “What’s next?”

I’m pleased to say that I can finally answer that question. Let me tell you about Responsive Field Day.

Responsive Images 101, Part 5: Sizes

When we last left our intrepid web developers, they had discovered the power of srcset width descriptors, only to be faced with a new challenge—the browser only knows the size of the viewport when it begins downloading images.

Now, it is time to meet the hero of our story: the sizes attribute.

sizes-hero

Sizes attribute is required!

The sizes attribute is required any time you use srcset width descriptors.

In fact, sizes only makes sense if you’re using the width descriptors. If you’re using the display density descriptors, you don’t need the sizes attribute. The browser won’t know what to do with it.

Sizes syntax

Out of all the new responsive images standards, sizes was the hardest one for me to wrap my head around at first.

Sizes syntax repeated below

Like srcset, the sizes attribute contains a comma-separated list. This comma-separated list describes the size of the image in relation to the viewport.

I want to repeat that point because it is the key to understanding sizes.

We’re telling the browser what size the image will be in relation to the size of the viewport. And we can tell the browser how that relationship changes as the size of the viewport changes.

<img src="cat.jpg" alt="cat"
  srcset="cat-160.jpg 160w, cat-320.jpg 320w, cat-640.jpg 640w, cat-1280.jpg 1280w"
  sizes="(max-width: 480px) 100vw, (max-width: 900px) 33vw, 254px">

Like srcset, each comma-separated item contains two values separated by a space.

Media conditions

The first value is a media condition. A media condition is similar to a media query, but not as full featured. For example, you can’t do things like ‘@media screen’, but you can do everything else you would likely want to do in sizes.

Most commonly, your media condition is going to be a something like ‘(max-width: 480px)’ or maybe ‘(min-width: 480px)’.

Lengths

The second value in each comma-separated item is a length. This length is often expressed using the viewport width (vw) unit.

There’s a good chance you haven’t seen vw units before. They are fairly new, but have wide support in current browsers.

Each vw unit represents 1% of the viewport width, which is a fancy way of saying that 100vw is 100% of the viewport width and 33vw is 33% of the viewport width.

The length doesn’t have to be expressed as a viewport width unit. It can be any length including absolute and relative length. You can even use CSS calc() to do things like auto-calculate margins dynamically.

How does the browser select the correct sizes value?

When the browser starts through the comma-separated list of values, it grabs the first value where the media condition passes.

Take another look at our sample markup and the order in the sizes attribute:

<img src="cat.jpg" alt="cat"
  srcset="cat-160.jpg 160w, cat-320.jpg 320w, cat-640.jpg 640w, cat-1280.jpg 1280w"
  sizes="(max-width: 480px) 100vw, (max-width: 900px) 33vw, 254px">

If we translated this into a bulleted list of instructions, it might look like this:

  • (max-width: 480px) 100vw — If the viewport is 480 pixels wide or smaller, the image will be 100% of the viewport width.

  • (max-width: 900px) 33vw — If the viewport is 480 pixels wide or smaller, this rule will never be reached because of the previous media condition. Ergo, if this rule effectively says that if the viewport is 481 pixels wide to 900px, that the image will be 33% of the viewport width.

  • 254px — When there is no media condition listed, the length is assumed to be a default value used when none of the other media conditions are met. In this case, we have media conditions covering viewports up to 900 pixels. Therefore, from 901 pixels wide to infinity, the image will be 254 pixels wide.

To help you visualize how this might work in the real world, I created a little video that looks as how the values might change as the viewport width increased on the Walmart Grocery site.

NOTE: As of the time of publication, the Walmart Grocery site was not using srcset and sizes. This is hypothetical markup. If you want to see srcset and sizes in action, take a look at The Guardian which recently switched to using srcset and sizes.

But what about separation of content and presentation?

I’ve seen many complaints about the new responsive images specification. Most amount to either complaints about complexity that ignore the fact that images on the web are inherently complex3 or some variation of WWIC.

But the one complaint I have a tremendous amount of sympathy for is the idea that we now have presentation information—the size of the image—in the markup. I doubt there was anyone involved in the responsive images standards process who didn’t share this concern at some point.

Unfortunately, it is unavoidable. As discussed in Part 4, the browser starts downloading image sources before the size of the image in the page is known.

The only way to support the pre-loader and make sure the right source gets downloaded is to provide some information about the size of the image in the markup.

Is the pre-loader worth it?

If you’re like me, you may have found yourself wondering whether the pre-loader was worth all of the problems it causes?

Yes. Yes, it is.

pre-loader-faster-web

Andy Davies wrote about how Google saw a 20% and Firefox a 19% increase in average page speed after implementing the pre-loader. Steve Souders thinks that “preloading is the single biggest performance improvement browsers have ever made.”

We can’t simply throw out that web performance boon in favor of responsive images.

Therefore, we have to find a compromise. The sizes attribute is that compromise. It provides just enough information for the browser to do its job.

Srcset and sizes = Smart browsers

Srcset and sizes provide all of the functionality you need for the resolution switching use case. They give the browser just enough information to allow it to make smart decisions.

Dog with glasses

But what happens when you need more control? What about art direction?

Next Tuesday, Responsive Images 101, Part 6: The Picture Element.


Responsive Images 101 Series
  1. Definitions
  2. Img Required
  3. Srcset Display Density
  4. Srcset Width Descriptors
  5. Sizes
  6. Picture Element
  7. Type
  8. CSS Responsive Images
  9. Image breakpoints

Footnotes
  1. How quickly we forget web-safe colors, Lynda Weinman‘s multiple books on web graphics, and the way different images formats compress. And it’s not getting any simpler. Images on the web are inherently complex.
  2. Super hero by Ashley Rose. Dog Intelligence by Alice Jamieson. Licensed under Creative Commons.