Dealing with Content Images in Email

Published by Chris Coyier

Let's say you're using an RSS-to-Email service. They're pretty useful. Plenty of people like subscribing to content via email. You have a CMS that generates RSS from the content you create. An RSS-to-Email service can watch for new entries, format those new entries into an email, and send them out to a list of subscribers. MailChimp and Campaign Monitor both offer this service and I'm sure they aren't the only ones.

But how do you handle images within those email-generating entries? It can be a little tricky actually, because the HTML for images that works on the website might not be so great in email.

Here's an example. You write a blog post, and the content of that blog post spits out like this:

<p>Blah blah blah. Blog post about ponies. Here's a cool and hip pony:</p>

<img src="http://cdn.ponies.what/pony.jpg" width="1200" height="800">

<p>Isn't that the best pony of all?</p>

Notice the width and height attributes. That's not entirely uncommon. WordPress automatically adds them by default if you use the Media Uploader thingy.

Even if you remove them, that pony.jpg file is still 1200x800px big, and will render that way. That's no big deal, layout-wise, on the web, because we have CSS there. We can do the classic

article img {
  max-width: 100%;
  height: auto;
}

to ensure the image doesn't break the bounds of the container it is in, or stretch it wider than appropriate. The fact that the image is that size is reasonable. That would be a @2x version of a content image in a 600px wide column, which is what is needed sometimes to make a raster image look nice and sharp.

We might even employ a responsive images technique, utilizing both JavaScript and CSS. Also a smart and reasonable thing you might want to do.

But we don't have either CSS or JavaScript available to us in emails. So that 1200x800px image is going to render at 1200x800px in an email layout. That's bad. Even on desktop, that's obnoxiously wide and hurts the ability to comfortably read the email as it can cause horizontal scrolling.

I used to use FeedBurner to provide email subscriptions on this site, and this is the kind of thing people would get.


Horizontally scrolling emails. My favorite.

It's not a problem isolated to FeedBurner. I switched to MailChimp for this service more recently. It's not their "fault", but huge images break their email layouts as well. Here's a classic example where you click "Display images below" in Gmail to reveal images and by doing so you kinda break the layout:

So we're going to need to fix this at the HTML level.

Altering the HTML

We're going to need to:

  1. If the <img> has width/height attributes, remove them
  2. Add a new width attribute with a friendly value

So these:

<img src="image.jpg" width="1200" height="800">

<img src="image.png" alt="image">

Become:

<img src="image.jpg" width="320">

<img src="image.png" width="320" alt="image">

Simple enough of a plan, but how do you actually do it?

One way is to put Email-friendly with attributes on the <img> in the content to begin with, and allow the image to be bigger with CSS on your site if needed.

Another way is to create a special feed that parses the content and alters the attributes on the <img>s as needed. I'm a fan of this way, because then it gives you a place to make other special alterations intended for email-only.

Solving in WordPress

Russell Heimlich helped me with this in this forum thread. Thanks Russell!

You'll need a create a new RSS feed in WordPress just for this. Fortunately WordPress makes this easy with add_feed(). For your functions.php file, or a custom plugin:

function css_tricks_custom_feeds() {
  add_feed('email', 'get_me_the_email_feed_template');
}
add_action('init', 'css_tricks_custom_feeds');

The email string creates a new feed with the slug email, so there is now a new feed URL at:

http://css-tricks.com/feed/email/

The get_me_the_email_feed_template string references a callback function:

function get_me_the_email_feed_template() {
  add_filter('the_content_feed', 'css_tricks_super_awesome_feed_image_magic');
  include(ABSPATH . '/wp-includes/feed-rss2.php' );
}

Which references a filter function. This filter function does the magic of altering the HTML in a post.

function css_tricks_super_awesome_feed_image_magic($content) {
  // Weirdness we need to add to strip the doctype with later.
  $content = '<div>' . $content . '</div>';
  $doc = new DOMDocument();
  $doc->LoadHTML($content);
  $images = $doc->getElementsByTagName('img');
  foreach ($images as $image) {
    $image->removeAttribute('height');
    $image->setAttribute('width', '320');
  }
  // Strip weird DOCTYPE that DOMDocument() adds in
  $content = substr($doc->saveXML($doc->getElementsByTagName('div')->item(0)), 5, -6);
  return $content;
}

This really did feel magical to me. I had no idea PHP had the native ability to query a chunk of HTML like it was the DOM and adjust attributes and stuff, like JavaScript can. But it does. Shows what I know.

Note that if the image you are inserting into the RSS entry is via something like the_post_thumbnail (the "featured image") feature in WordPress, you're already doing something special to get that into the feed, so you'd use the_post_thumbnail('medium'); instead of the_post_thumbnail('large'); or whatever.

Use the new feed

Now that this new feed exists, you can point the RSS-to-email service at it. For CSS-Tricks, I'm using MailChimp and it slurps in that feed:

MailChimp also does it's best, via media queries in the email, to make the template small screen friendly:

And it works!

I should say, it works in mobile email clients that support media queries. Which does not support GMail apps on iOS or Android, which is unfortunate.

Mobile first?

Given how often email is read on small screen devices, it's tempting to make the email template a good width for small screens, and only stretch it for large screens. If you go with a wide fixed width, even if you adjust with a media query, non supporting browsers will have a bad time:

I spoke a bit with Fabio Carneiro, the master of emails for MailChimp, who has some ideas about mobile-first emails that will work with apps that don't support media queries.

I'll update this when we can get that going. I'd also like to try setting width="100%" on images so that they just fit the container rather than the width="320" thing I'm doing now. I was just kinda afraid the 100% would still stretch the container where 320 for sure won't. Needs more testing.

I've had some luck with a <table> based design where there is no fixed width, but only max and min...

<!-- main content-wrapping table -->
<table style="min-width: 320px; max-width: 600px;">

</table>

But I can't 100% vouch for that yet.