Using theme_picture for responsive images in Drupal 7

December 01, 2015

The Picture module helps you to use Drupal’s image creation capabilities to set up responsive images using the picture element. It’s a backport of the Responsive Image module in Drupal 8 core.

A friend of mine creates an online photo advent calendar every year - I previously wrote about how I built the site, and ahead of this year’s edition, I wanted to improve its performance. It’s an image-based site, so responsive images were the obvious target. The other item on the hit list was inline critical CSS, which is pretty easy, thanks to this tutorial from Chris Ruppel of Four Kitchens.

With the help of a tutorial from ThinkShout I was able to get up and running with setting up breakpoints and responsive image styles.

However, for some custom theming requirements, I needed to do some fiddling with the markup around the images, so I couldn’t just render the items as normal.

I was fairly familiar with using theme_image_style in preprocess_node to do this kind of thing with images, but couldn’t find any documentation on achieving the same thing with the picture module.

Digging into the code, I could see that there is a theme hook called picture, which was clearly what I wanted - like theme_image, it takes an array of variables, with the file URI, width, height, alt, attributes, and crucially an array of breakpoints. Trouble was, I couldn’t find any documentation on the expected format of those breakpoints, or where I could get the values. A quick look at the code of the breakpoints module yielded some likely-looking functions, but nothing that .

With a bit of poking around in the output of dpm (from the devel module) I was able to see that the render array for the field included a #breakpoints array, so I was able to pull that out and pass it in to theme_picture.

foreach ($vars['content']['field_images'] as $key => $value) {
  if (is_numeric($key)) {
    if ($value['#item']['type'] == 'image') {
      // Extract and transform the image title.
      $text = mytheme_text_transform($value['#item']['title']);
      $value['#item']['title'] = '';

      $picture_vars = array(
        'uri' => $value['#item']['uri'];,
        'breakpoints' => $value['#breakpoints'],
        'style_name' => 'large',
      );

      $picture = theme('picture', $picture_vars);

      $images[] = $picture . $text;
    }
  }
}

$vars['images'] = theme('item_list', array(
  'items' => $images,
  'attributes' => array(
    'class' => 'day-images',
  ),
));

By way of comparison, here’s the old version of the code which used theme_image_style:

foreach ($vars['content']['field_images'] as $key => $value) {
  if (is_numeric($key)) {
    if ($value['#item']['type'] == 'image') {
      $image_vars = $value['#item'];
      $image_vars['path'] = $image_vars['uri'];
      $image_vars['style_name'] = 'large';    
      $image = theme('image_style', $image_vars);

      // Extract and transform the image title.
      $text = mytheme_text_transform($image_vars['title']);
      $image_vars['title'] = '';

      $images[] = $picture . $text;
    }
  }
}

$vars['images'] = theme('item_list', array(
  'items' => $images,
  'attributes' => array(
    'class' => 'day-images',
  ),
));