Hướng dẫn Responsive Images với Drupal 8 Site

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.ymlfile 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

Hướng dẫn Responsive Images với Drupal 8 Site

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 inyourthemename.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

Screen Shot 2015-10-08 at 11.21.51 AM

Now I’ve got a slew of image styles all ready to go!

Screen Shot 2015-10-09 at 2.04.35 PM

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,
      images/kitten-big@2x.png 2x">
  <source 
    media="(min-width: 768px)"
    srcset="images/kitten-med.png,
      images/kitten-med@2x.png 2x">
  <img 
    src="images/kitten-sm.png,
      images/kitten-sm@2x.png 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.

Screen Shot 2015-10-09 at 3.02.21 PM

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.

Screen Shot 2015-10-08 at 1.50.07 PM

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:

Test Responsive Image Styles | Drupal 8 Test-2

And a small version on a HD screen:

Test Responsive Image Styles | Drupal 8 Test-3

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.