Automatically Get Responsive Images With Foundation Interchange In WordPress

What’s Interchange?

I’m a big fan of Zurb Foundation. If you aren’t familiar with Foundation, it’s a responsive front-end framework that allows you to quickly build mobile friendly sites and apps. They also pack together a few helpful JavaScript plugins. I recently dug into one called Interchange. It allows you to use media queries to dynamically swap out different image sources for different devices.

Why use different Image sources?

You really only want to load large resources for devices that handle it well. (Your iPhone on 3G doesn’t need a 2MP header image). It’d be nice if you could serve an equivalent image at, say, 600px wide (and 10KB) instead.

Manually Type an Interchange Tag? No thanks.

Once you read up on how to use Interchange in your markup, you’ll quickly figure out that if you (or your clients) use WordPress to manage images it’ll be a pain to manually insert markup like this for your posts & pages:

Taking a moment to dissect this… Interchange will read the data attribute and determine that for any device with a minimum width of 1px (mobile) we should load the default.jpg (which is small). But once the minimum width reaches 1280px, we should load the bigger, hi-res version. Wouldn’t it be great if you could just use the WordPress editor like normal?

I strongly believe you should keep your content clean, meaning don’t create hard dependencies on third party plugins (like Interchange). Imagine you have dozens or hundreds of Interchange tags all throughout your content and decide someday to move away from Interchange. What a pain it would be to cleanup your content!

Instead, let’s capture the actual <img> tag before it’s output, replace it with an Interchange tag, and then display it. If you ever decide to move away from Interchange, just remove the filter!

The strategy

From a big picture, we need to:

  • Add some custom image sizes to your theme (these are the mobile sizes that WordPress will automatically generate when you upload a large image for your content).
  • Add a filter to the content of your theme so that before we render the page, we can swap out your image tags for Interchange markup.
  • Get Foundation Interchange up and running in your theme.
Generate Mobile Images

How small should we make our mobile images? Well, to keep this example simple, let’s just do one: 640px x 480px. Let’s assume a mobile device with a 640px landscape viewport doesn’t need an image larger than 640px wide. (We’ll ignore retina for now). So add this custom image size to functions.php:

You probably have existing images in your content. Adding this will not automatically generate copies at this size for you. I recommend using the Regenerate Thumbnails plugin to build these sizes for all your older, existing uploads. If you don’t do this, nothing will break, but your older posts won’t benefit.

Filter Your Image Tags

Add the following to functions.php:

Now Use Interchange

Next, you need to load foundation.js and foundation.interchange.js. Typically you’ll have a build process to concatenate / minify your scripts, but you can also just enqueue them traditionally.

Finally, initialize Foundation in your site / global JavaScript! You should be done!

23 thoughts on “Automatically Get Responsive Images With Foundation Interchange In WordPress

  1. Thanks for this great article, clear and well commented
    We have applied our website based in foundationpress and works great
    After some testing we have several basic questions:
    How to enter the rest of sizes that correspond with other resolutions screens?
    How display in retina devices?
    thank you

    1. Thanks Bigara,

      In my code sample there are only a few edits you would need to make in order to add more image sizes and breakpoints.

      First, you’ll want to have WordPress generate more image sizes based on your breakpoints. For example, if you want to generate a “medium” image you would add that like so (see add_image_size.php above):

      add_image_size(‘mobile-small’, 640, 480);
      add_image_size(‘mobile-medium’, 960, 720);

      Next, you would modify replace_images_with_interchange(), lines 54-58 like so…

      $mobile_image_small = wp_get_attachment_image_src($attachment_id, ‘mobile-small’);
      $mobile_image_medium = wp_get_attachment_image_src($attachment_id, ‘mobile-medium’);
      $standard_image = wp_get_attachment_url($attachment_id);

      if ($mobile_image_small && $mobile_image_medium && $standard_image) {

      $interchange_tag = ‘ data-interchange=”[‘ . $mobile_image_small[0] . ‘, (only screen and (min-width: 1px))], [‘ . $mobile_image_medium[0] . ‘, (only screen and (min-width: 641px))], [‘ . $standard_image . ‘, (only screen and (min-width: 961px))]”‘;

      A few notes on the changes above…

      You should choose and customize those sizes based on your own design. You might want the smallest mobile image version to be 320px wide for example.

      – The general format of these Interchange tags is

      data-interchange=”[image_path, (media query)], [image_path, (media query)], [image_path, (media query)]”

      – You can put any media query in there for each image, so for retina you may want to do a media query like so:

      only screen and (min-resolution: 192dpi)

      The Foundation Docs have a lot more detail on how to specifically use Interchange http://foundation.zurb.com/docs/components/interchange.html

      Hope that helps!

      1. Thanks Jared,

        With your clear explanations and the Foundation docs, we have responsive images with interchange. Retina looks well y different devices.

        Here is the part of the code in interchange.php (loaded by functios.php):

        ///////////////////////////////////////////////////

        if ($attachment_id) {

        $mobile_image_small = wp_get_attachment_image_src($attachment_id, ‘mobile-small’);
        $mobile_image_medium = wp_get_attachment_image_src($attachment_id, ‘mobile-medium’);
        $mobile_image_large = wp_get_attachment_image_src($attachment_id, ‘mobile-large’);
        $standard_image = wp_get_attachment_url($attachment_id);
        $retina_small = wp_get_attachment_image_src($attachment_id, ‘retina-small’);
        $retina_medium = wp_get_attachment_image_src($attachment_id, ‘retina-medium’);
        $retina_large = wp_get_attachment_image_src($attachment_id, ‘retina-large’);

        if ($mobile_image_small && $retina_small && $mobile_image_medium && $retina_medium && $mobile_image_large && $retina_large && $standard_image) {

        $interchange_tag = ‘ data-interchange=”[‘ . $mobile_image_small[0] . ‘, (only screen and (min-width: 1px))], [‘ . $retina_small[0] . ‘, (only screen and (min-width: 1px) and (-webkit-min-device-pixel-ratio: 2), only screen and (min-width: 1px) and (min–moz-device-pixel-ratio: 2), only screen and (min-width: 1px) and (-o-min-device-pixel-ratio: 2/1), only screen and (min-width: 1px) and (min-device-pixel-ratio: 2), only screen and (min-width: 1px) and (min-resolution: 192dpi), only screen and (min-width: 1px) and (min-resolution: 2dppx))], [‘ . $mobile_image_medium[0] . ‘, (only screen and (min-width: 641px))], [‘ . $retina_medium[0] . ‘, (only screen and (min-width: 641px) and (-webkit-min-device-pixel-ratio: 2), only screen and (min-width: 641px) and (min–moz-device-pixel-ratio: 2), only screen and (min-width: 641px) and (-o-min-device-pixel-ratio: 2/1), only screen and (min-width: 641px) and (min-device-pixel-ratio: 2), only screen and (min-width: 641px) and (min-resolution: 192dpi), only screen and (min-width: 641px) and (min-resolution: 2dppx))], [‘ . $mobile_image_large[0] . ‘, (only screen and (min-width: 1025px))], [‘ . $retina_large[0] . ‘, (only screen and (min-width: 1025px) and (-webkit-min-device-pixel-ratio: 2), only screen and (min-width: 1025px) and (min–moz-device-pixel-ratio: 2), only screen and (min-width: 1025px) and (-o-min-device-pixel-ratio: 2/1), only screen and (min-width: 1025px) and (min-device-pixel-ratio: 2), only screen and (min-width: 1025px) and (min-resolution: 192dpi), only screen and (min-width: 1025px) and (min-resolution: 2dppx))], [‘ . $standard_image . ‘, (only screen and (min-width: 1441px))]”‘;

        $content = substr_replace($content, ‘data-old-‘, $src_full_content_start_pos, 0);
        $content = substr_replace($content, $interchange_tag, $image_tag_start_pos + 4, 0);
        }
        }
        ///////////////////////////////////////////////////

        Here is the responsive-image.php (loaded by functios.php):

        ///////////////////////////////////////////////////

        add_image_size(‘mobile-small’, 640, 480);
        add_image_size(‘retina-small’, 1024, 720);
        add_image_size(‘mobile-medium’, 1024, 720);
        add_image_size(‘retina-medium’, 1600, 1440);
        add_image_size(‘mobile-large’, 1600, 1440);
        add_image_size(‘retina-large’, 1920, 1600);

        ///////////////////////////////////////////////////

        hopes that helps somebody else and thanks again!

  2. Hi Jarad,
    Many thanks for your very useful script. I spent a long time trying to implement responsive images with picturefill with srcset but just don’t like the hurdles with double-downloading etc. I’m also using foundation with interchange and have used your implementation now with some variations. I’m adding additional image sizes so they are available in the Media Manager too. Then I have written some conditionals with different interchange variables based on your $interchange_tag for images going full width and also for smaller instances i.e. 6 columns.

    Thanks again for your hard work which made it possible for me to integrate as I want.
    Cheers
    otti

      1. Hi Jarad,
        Just one question if I may: I have tried unsuccessfully to include the tag after the interchange declaration. I’m only able to add it after the tag and therefore separate from the tag. Any help here would be much appreciated.
        Cheers
        otti

        1. Gotcha… I actually never did implement a tag in my example but I think I understand what you’re trying to do. (You want to have a normal tag inside of your tag as a fallback in case a user has disabled JavaScript?)

          Notice in my code sample I’m setting a position marker on line 34. I actually haven’t set any markers for right after the image tag… Only the start of the image tag.

          What if you included your right before the image? It should have the same effect when JavaScript is off.

          1. Yep, this is exactly what I try to achieve. You are right, the tag in front of the tag should not be an issue. The problem is that WordPress wraps each image added with the Media Uploader into a tag. Therefore I’m not sure how I can add the tag just before the tag. Any ideas?
            Thanks again for your help!
            otti

          2. I see. I think maybe your theme or perhaps a plugin that’s installed is creating those tags… I’m not seeing that behavior in my own site (from the media uploader). It sounds like you might need to either find out what’s creating those (to remove them) or possibly filter them out (in a similar way to how I’m filtering out p tags around my images like this https://github.com/jaredcobb/jaredcobb.com/blob/master/lib/class-theme.php#L19).

            Alternatively it sounds like you might just need to adjust the `preg_match_all()` and `str_pos()` functions in my example to take the tags into account.

            Last solution… You can not worry about users who disable JavaScript. 🙂 Half joking, half serious… But if someone has JavaScript disabled nowadays then the entire internet is an incredibly broken experience for them anyway.

          3. I know what you are saying with possibly not worrying about the tag. I’m the same as you with 50% thinking it is not really important anymore and I maybe should focus on more important items on the endlessly long web development list 🙂

            I will need to learn a bit about the regex as I haven’t done anything with it before in order to be able to change your functions. But this is a good thing anyway – might need it more often.

            I’m using foundationpress as my base theme but have modified quite a bit in order to develop my own base theme which I can use for almost all my projects.

            I will keep you posted about my success with it all.

  3. Hi Jarad, the code you have posted works perfectly when I add it to my functions.php file however my current functions.php file is calling separate includes (basically to keep it modular) and when I add your code to an include file it doesn’t seem to work. An example of an include I have in my functions.php file is below:

    // Include example
    require_once(get_template_directory().’/assets/functions/jarad-interchange.php’);

    Is there something that I need to change in the include file to make it work?

    Thanks,
    Jack

    1. Hi Jack,

      That’s strange because I’m using this technique on my site (here) and I also have this same function in a module (it’s a method on a class in a subfolder too).

      Are you getting any error messages? (You might need to enable debugging by setting WP_DEBUG = true; in your wp-config.php file).

      Note also that this is actually two functions and `replace_images_with_interchange()` requires that `get_attachment_id()` is accessible.

  4. Hi Jarad, I just updated to WP 4.3 and I receive this message when I had debug set to TRUE:

    Strict Standards: Only variables should be passed by reference in /Users/jackfearing/Sites/o2/wp-content/themes/JointsWP-CSS-master/assets/functions/interchange.php on line 144

    I read something online about exploding the values but wasn’t sure that was the thing to do or how to do it.

    Any thoughts?

  5. Hey Jared, I currently using your code (which works perfectly using the native WP editor) and was wondering if there was a way to also be able to extend the function so that interchange could also work when using Advanced Custom Fields’s WYSIWYG editor?

    1. Hi Jarad, just wondering if you had a chance to take a look at my last post regarding extending your function to ACF WYSIWYG editors?

      1. Actually I think I figured it out. I added an additional filter in the functions file which seems to work.

        add_filter( ‘the_content’, ‘replace_images_with_interchange’ );

        add_filter( ‘acf_the_content’, ‘replace_images_with_interchange’ );

        1. Hey Jack,

          Sorry I didn’t have a chance to look into this, but looks like you got it working anyway! Thanks for posting the solution back here, I’m sure the next person will appreciate it.

  6. Hi Jarad, I just upgrade to the latest version of Foundation (ver.6) and I’m having an issue with displaying images using your interchange code above. Does your code work with the latest version?

    1. After playing around with the code it looks like Foundation made an update to their syntax. I removed the parentheses around the media queries and is seemed to work. Below is a before/after snippet once I made the change.

      Before:
      ———————
      $interchange_tag = ‘ data-interchange=”[‘ . $mobile_image_small[0] . ‘, (only screen and (min-width: 1px))], [‘ . $mobile_image_medium[0] . ‘, (only screen and (min-width: 641px))], [‘ . $standard_image . ‘, (only screen and (min-width: 929px))]”‘;

      After:
      ———————
      $interchange_tag = ‘ data-interchange=”[‘ . $mobile_image_small[0] . ‘, only screen and (min-width: 1px)], [‘ . $mobile_image_medium[0] . ‘, only screen and (min-width: 641px)], [‘ . $standard_image . ‘, only screen and (min-width: 929px)]”‘;

  7. Jarad, I just ran across this article and this sounds like a great usage of Interchange working with WordPress. While the goal of this is of course faster load times by only serving the singular relevant image to the user’s viewport size, have you done any testing on whether the additional filters and processing you’ve added increases page rendering time?

  8. Hi Jared, I have your script working on my site however I was wondering if there was a way to have it also include the post_thumbnail images are as well. I tired adding “add_filter( ‘the_post_thumbnail’, ‘replace_images_with_interchange’ );” to your script but that did;t seem to work.

    1. I think I figured it out. I change the call from “the_post_thumbnail” to “post_thumbnail_html” which seems to work. For is the final code: add_filter( ‘post_thumbnail_html’, ‘replace_images_with_interchange’ );

Leave a Reply

Your email address will not be published. Required fields are marked *

Credits

Zurb Foundation

The most advanced responsive front-end framework in the world.
http://foundation.zurb.com/

Underscores

A starter theme for WordPress
http://underscores.me/

VileR’s Oldschool PC Font Resouce

Home of the world’s biggest collection of classic text mode fonts, system fonts and BIOS fonts from DOS-era IBM PCs and compatibles
http://int10h.org/

Sierra Entertainment

The best game publisher. Ever.