It's 2021 and providing good user experience around images has never been more challenging. It's one of the most elemental components of functional web design. With high-resolution screens and lots of mobile devices at various browser sizes, developers need to tackle a fundamental tradeoff between fast user experience (smaller images) and high-quality user experience (larger images). Luckily - like image cache/image styles before it - the Drupal community has developed a tool that makes this challenge much more manageable: the Picture module.
But first, let's review what functionality we want around the display of images:
- Minimize bandwidth demands on the visitor
- Provide images of a resolution appropriate to the visitor's device
- Tailor scaling, cropping and other processing (image styles) to screen size
In other words, we want to both maximize performance and ensure high-quality art direction on our sites. Luckily, new HTML techniques - srcset and picture - have been advanced to provide the sophistication needed to meet these needs. The details of how these work are outside of the scope of this article, but you can find lots of background(link is external) articles(link is external) if you're interested. Suffice to say that the picture element provides multiple image sources to the browser, along with instructions regarding which to load for the visitor. The browser then only downloads and displays the appropriate image source.
The Picture module(link is external) takes care of all the low-level mechanics for you. It works extensively with two other modules: core's Image Styles and Breakpoints(link is external). The high-level steps are as follows:
- Decide the screen widths at which your site's design will change in a responsive manner (breakpoints)
- Identify the art direction needed for images on the site
- Create image styles that provide the proper art direction and resolution for each width (image styles)
- Map sets of image styles to breakpoints (picture mappings)
It's worth reading the documentation(link is external) on breakpoints, especially the warning(link is external) about how to order them. The process is a little picky. This step codifies the "what" you are responding to in your responsive web design. These are generally the same widths that your theme already has in the form of media queries in its CSS. Deciding on breakpoints is also outside of the scope of this article (and somewhat dependent on your theme's design), but let's just use these as an example:
- wide: (min-width: 1200px)
- normal: (min-width: 979px)
- narrow: (min-width: 768px)
- mobile: (min-width: 0px)
Breakpoints are set at Admin menu > Configuration > Media > Breakpoints. Make sure to check the multiplier checkboxes - ie "2x" - that you want in order to serve higher resolution images to devices with "retina" style screens. Once set, save your breakpoints to a group.
Art direction is another subjective question that mostly depends on your theme and content needs. Art direction is a term that covers all of the visual choices you make about presenting images on the site. Does the image take up the full width of the column, or only a certain fraction of it (with text flowing around)? Is the image cropped a certain way? Is a watermark or other effect applied to it?
These are questions we're used to answering via Image Styles. However, there's a potential extra wrinkle when considering responsive design: does the art direction change when the screen size changes? What if you have a really wide-and-short (super landscape) image style? That works well on desktop but might obscure important details from the image on a skinny screen. You might choose a different art direction in that case. Perhaps cropping the image so that it is relatively taller (and narrower). Like breakpoints, these are really design and user experience decisions. Drupal configuration flows from them.
OK, you have breakpoints and art direction. Here's the tedious part: now create an image style for (almost) each combination of art direction and breakpoint. Let's say you decided you want one art direction where the image is the full width of a column (called 'article-full-width'), and another where the image is only a third of the column's width (called 'article-third-width'). Let's assume that the column is 66% the width of the layout at breakpoints narrow and above (below that, 100% of the width), and maxes out at 1000 pixels wide (even on a desktop with a large screen). Here are the styles you'd need, given the example breakpoints above:
- article-2000 (scaled to 2000px width)
A lot of styles, huh? I've created a spreadsheet that demonstrates the calculations I'm doing to decide on these. Given the permutations of browser width, column width, image-width-as-fraction-of-column, and mobile exceptions, it's not easy to keep track in my head.
Here's where everything comes together. A picture mapping is what drives how Picture module spits out the picture HTML elements. Think of each picture mapping as a distinct art direction (or a set of related art directions, in cases where browser width changes the art direction). For that art direction, it maps an image style to each of your breakpoints. In this example, we'd create just two mappings:
- Article - Full width
- wide 2x : article-2000
- wide 1x : article-1000
- normal 2x : article-1584
- normal 1x : article-792
- narrow 2x : article-1294
- narrow 1x : article-647
- mobile 2x : article-1536
- mobile 1x : article-768
- Article - Third width
- wide 2x : article-660
- wide 1x : article-330
- normal 2x : article-524
- normal 1x : article-262
- narrow 2x : article-428
- narrow 1x : article-214
- mobile 2x : article-508
- mobile 1x : article-254
Note that in our examples above, the mobile styles are actually wider than some of the others, because, in this example, the theme's design switches the column to full-browser-width and the image to full-column-width when the browser is under 768px wide.
Apply your mappings to image fields
Now you have the Picture system completely set up. But not yet doing anything! The last step is to activate the system for displaying content. One of the easiest ways to do that is to use Picture to display the content of image fields. I'll assume you already have a Content Type configured that has at least one Image field:
- Go to Admin > Structure > Content Types > [your content type]
- Click the Manage Display tab
- Under the Format column, choose "Picture" in the drop-down associated with the image field
- Click the "gear" icon to change display settings for the field
- Choose the appropriate Picture mapping value
- Click "Update"
- Click "Save"
Great! Now your image field is set to display the image as a Picture element. Clear caches as necessary, and check out your content at a variety of browser widths.