Celebrating the first release candidate for Drupal 8, the Advomatic team has been testing things out, diving into not-so-well documented (yet!) waters. Here’s a little tutorial for doing something that had us scratching our heads for a bit: adding responsive images in Drupal 8.
Here’s what you will need:
- A Drupal 8 install (Breakpoint and Responsive Image modules are already in core)
- Make sure Breakpoint module is enabled (already enabled by default in core)
- Turn on the Responsive Image module
Setting up your breakpoints
Since Breakpoint module was added to D8 core, you can now define your theme’s breakpoints in code (and categorize them into breakpoint groups – for example, one group for image-sizing breakpoints and one for layout-related breakpoints). There is no UI for doing this, but Breakpoint module gives us an API that allows modules and themes to define breakpoints and breakpoint groups, as well as resolution modifiers that come in handy when targeting devices with HD/Retina displays.
To do this from your theme, simply create a
yourthemename.breakpoints.yml file in the root of your theme directory. For the purposes of simplifying this tutorial, we will be creating two, simple, device-agnostic breakpoints: “small” and “large.” Under normal circumstances we would be using more.
yourthemename.small: label: small mediaQuery: '(min-width: 0px)' weight: 0 multipliers: - 1x - 2x yourthemename.large: label: large mediaQuery: 'all and (min-width: 960px)' weight: 1 multipliers: - 1x - 2x
The weight of these is crucial so that the proper image styles get swapped in depending on viewport size and screen resolution. Here, a breakpoint’s weight should be listed from smallest min-width to largest min-width. Modules, however, can reverse that order if needed, as the Responsive Images module does.
Also, note the “multipliers” section. Breakpoint allows for different pixel density multipliers for displaying crisper images on HD/Retina displays: 1x, 1.5x and 2x. More on that below.
Determine what image styles you will be using for each breakpoint
Depending on how many breakpoints you have, you will need to plot out what your image sizes will be for each breakpoint range. In our case, we’ll do a simplified version with just two image styles, one for each of our breakpoints.
As an aside, here’s an interesting presentation on doing the math for your responsive images before you even get to Drupal. The presenter, Marc Drummond from Lullabot, uses a rule of 25% to choose his image styles. For a hero image, for example, he starts with 320px (generally, your starting maximum width). Then he picks his next breakpoint at 320 x 1.25 — 400px, then 400 x 1.25 — 500px … on up through 1600px (tidying up the numbers a bit to make more sense later).
Add your image styles at /admin/config/media/image-styles
Below is what I’ve chosen for my image styles, basing each on the largest width and height it will need to be before the next breakpoint snaps into place. I’m using a 16:9 aspect ratio across the board here to make crops, but yours may vary, based on the layout changes among breakpoints. These all use the “Scale and Crop” effect.
- feature-small (0-959px): 738px x 415px
- feature-large (960px & up): 938px x 528px
HD (and Retina) screens
At this point, you should seriously consider making a twice-as-large version of images for your high definition display users. For this step, you’ll need to make sure you have your breakpoints set up to accept 2x options (via the “multipliers” you set up in yourthemename.breakpoints.yml), and then add doubled-up image styles:
- feature-small-2x (0-959px): 1476px x 830px
- feature-large-2x (960px & up): 1876px x 1056px
Now I’ve got a slew of image styles all ready to go!
Intro to the Picture HTML element
Drupal 8 makes the big leap and uses the HTML5’s Picture element to display all our different image styles and pick the right one. It’s essentially a container that allows for multiple sources for a single image tag. Let’s see how it works.
Here’s a basic example of the picture element markup:
<picture> <source media="(min-width: 960px)" srcset="images/kitten-big.png, firstname.lastname@example.org 2x"> <source media="(min-width: 768px)" srcset="images/kitten-med.png, email@example.com 2x"> <img src="images/kitten-sm.png, firstname.lastname@example.org 2x" alt="a cute kitten"> </picture>
The source tag allows you to state your breakpoints and the image source to use in that case (with a regular and a 2x version). The img tag provides your fallback image — it will show when the others don’t apply. So the work we’ve done so far is basically providing all the parameters for the picture element that we’re building. Note that the source rules are listed from largest to smallest.
Next, create your responsive image style using those image styles at /admin/config/media/responsive-image-style
Now let’s put it all together in Drupal. Add a new responsive style, selecting the breakpoint group you are going to use here — in my case, I’m using my theme’s breakpoint group.
For each breakpoint, I’m choosing a single image style — but you can also choose to ignore that breakpoint, or even load multiple images styles based on different size criteria you specify.
Apply your responsive image style
In my case, I added a field to the Basic Page content type for the Feature Image. Set the Format Settings to “Responsive image” and select your new Responsive image style.
Now check your work. One thing that makes it a little more difficult is that the web inspector won’t tell you which version of the image is loading just by looking at the DOM; the picture element markup looks the same no matter what breakpoint you are in. Instead, you will need to peek at the browser’s web dev tools (such as the Network tab in Chrome) to see which version of the image has downloaded.
Here’s the wide version on a non-HD screen:
And a small version on a HD screen:
As you can see, this method can be as simple or complex as you need it to be. But I think Drupal 8’s new system allows for the flexibility for the range of devices and breakpoints we have now.