Email Development

While working at Disney, I learned about the many quirks of email development and the issues that each client brings to the table. Below are tips and tricks I have developed from experience or come across over the years. Feel free to contact me with any questions, help, or freelance opportunities.

General tips

The following are some general tips for email development.

DOCTYPE
Campaign Monitor did a lengthy write-up on which doctype should be used in emails in August 2014. I'm not going to summarize their section other than to say that you should use the XHTML 1.0 Transitional doctype.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


IE meta
If you care about how the view in browser version of your emails render in Internet Explorer, having the following meta tag tells IE to use the latest/best rendering options available. There is a very lengthy, but good answer to a Stacked Overflow question about the IE meta tag.
<meta http-equiv="X-UA-Compatible" content="IE=edge" />

Outlook Windows app

CSS background images
2007 and up — There should be no positioning or repeating style because Outlook 2007 and higher ignores these and will not work. Because of this, all backgrounds should be made to be repeatable both horizontally and vertically or be made large enough to cover the content area needed.


Padding-top on table columns
2007 and up — If you have multiple columns and have added a "padding-top" style to one column but not the other(s), Outlook will add the same amount of padding to the other columns. Even adding padding-top:0px; to the columns you do not want to have padding-top will still have it applied. The only solution is to avoid using "padding-top" on columns when there is more than one column in a row. If having different padding-top values per column is required, then you can create nested tables. All other padding sides are fine to have unique padding added to. Do not use margin to try and fix this as margin is completely or partially ignored in some clients.


Padding on tables
All versions — If you put any kind of top or bottom padding on a table instead of on the outer containing column, Outlook will add that amount of top and bottom padding to each column in that table. Outlook 2003 will add left and right padding to each column as well as top and bottom padding. Make sure that no padding is put on a table itself. The same applies to margin, but margin should not be used in email anyway.


Width and height
For all versions — Outlook will ignore width and height values that are set with CSS styles instead of with the width and height attributes, so be sure to set width and height values using attributes in addition to styles (to cover off on other clients).


Height
Outlook 2013 only — Height values on tables are ignored and will only make the table as tall as the content inside. If a table needs be a specific height, add it to the column(s) as well to ensure that the height is adhered to. Be sure to set this using the height attribute in addition to the height style.


15 pixel minimum table column height
Outlook 2013 only — It has a minimum height for columns of 15 pixels. The fix for this is to apply both font-size and line-height styles to make it be the desired height. Adding a height attribute or height style will not force it to be the specified height. The height attribute may still be needed for other clients though if it is an empty column and has no content to force the column to the desired height.


125% and 150% DPI image rendering
Outlook 2007 and up — Users can set their Windows computer's DPI to be either 100%, 125%, or 150%. With Outlook, this can cause issues with images. When looking at emails, it strangely only effects the layout and copy, but not images. Images are set to render at their actual true size while everything else gets scaled up around it. The fix for this is to include some Outlook-only VML code:
<!--[if gte mso 14]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>
96
</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
What this does is it tells Outlook 2010 and higher to scale images to properly fit the email design based on the current DPI setting that is already scaling the layout and copy. I found this discovery on the Litmus community forums. Now you may have noticed that 2007 is not covered. Based on the results of much testing by James White in the Litmus forums link, Outlook 2007 has some really weird bugs/results from including this snippet with "mso 12" to include 2007 instead of "mso 14". Since Outlook 2007 is three verisons back from the current offerings from Microsoft and since Outlook desktop app is insignificant as far as email viewership is concerned, it is probably a safe thing to not care about 2007.


Outlook style resets/defaults
Outlook 2007 and up — The following example shows how to include a secondary <style> tag just for Outlook that helps set some default styles and behaviors. It can also be used for making Outlook-only layout adjustments. This Outlook comment should be placed after your last (or only) <style> tag.
<!--[if mso]>
<style type="text/css">
img {
-ms-interpolation-mode:bicubic;
}
table {
border:none;
border-spacing:0;
border-collapse:collapse;
mso-table-lspace:0pt;
mso-table-rspace:0pt;
}
td {
border-collapse:collapse;
}
</style>
<![endif]-->
This Outlook-only style tag is also used in later examples covering stacking tables.


Forced page breaks
Outlook 2007 and up — Starting with Outlook 2007, the desktop Outlook app for Windows used Microsoft Word for its rendering engine (because that makes so much sense). As a result, if you have content that exceeds ~1700 pixels, it will result in a page break that can negaitvely effect your layout if where the break occurred was not at a visually natural break (i.e. a new row or table section). The way to fix this problem is to have a second all-encompassing table set to 100% width that would finish off the rest of your emails content to ensure that it doesn't break in a place you wouldn't want it to. If your email is in a two column layout, this page break can really be bad for your email.


!important
Outlook 2007 and up — According to Campaign Monitor's testing, Outlook will ignore any inline style that features "!important", so it is best to not use "!important" with inline styles unless you don't care about Outlook. The Campaign Monitor section does say that "!important" is ok to use with styles in the <head>.


Image border
Outlook 2007 and up — If you do not include border="0" in an <img /> tag, Outlook will add space around an image.


Button w/margin added to images
Outlook OWA — A rather silly thing in my opinion, but OWA will add a <button> tag around images and that button will have a default margin of 2px on all sizes. The simple fix is to add a style to your head styles:
button {
margin:0;
}

Gmail

Table widths
A few years ago, Gmail made some changes to the Android and iOS Gmail apps that altered their rendering behavior. That change was (I'm guessing based on what it does) an attempt to improve the readability of copy within an email by scaling it up. This can obviously yield broken email designs or unwanted layout shifts depending on your creative. The fix for Android, assuming you have a fixed width email, is to put width, min-width, and max-width styles on all tables that need a width set to them. For example:
<table border="0" cellpadding="0" cellspacing="0" width="520" style="width:520px; min-width:520px; max-width:520px;">
</table>
You'll notice that the width attribute is also set. That is because not all clients recognize the width styles. My memory is a bit fuzzy, but I'm pretty sure that client is Outlook 2007 and higher.


iOS Gmail table widths
If you were paying attention (yes, I'm a smartass), you'll have noticed I said the fix for Android and not iOS. The Gmail app on iOS has an extra step in order to make sure it can look the way you want your fixed email design to look. At the bottom of your email, put the following snippet right before your closing </body> tag:
<div style="display:none; height:1px; max-height:1px; white-space:nowrap; font-family:Courier; font-size:15px; line-height:1px;">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</div>
I found this little gem on the Litmus community forums. It basically forces the width of the rendered email to be about 600px wide. Now this snippet harkens back to the days of the Gmail app on iOS7. Email on Acid currently only renders that version and the last time I used Litmus, it was defintiely an older version. So it might not be needed anymore, but it doesn't hurt to include it.

UPDATE: It is possible this does not work anymore since Gmail is supposed to now support the "display" CSS property along with media queries. I have not done any testing with the iOS version since this change (9/30/2016), but it should be looked into for testing.


Underlines not present on links
Another potentially annoying thing with Gmail is that it removes underlines from links in emails. If you want to be sure that all links have an underline, you can simply include a text-decoration:underline style. For example:
<a href="#externalLink" target="_blank" style="color:#000000; text-decoration:underline;">External Link</a>


Character rendering limiation
The last thing to keep in mind about Gmail is that after about 100,000 characters, it stops rendering the email. And by characters, I mean every space, tab, letter, number, etc. So if you have a really long email, the layout could either be broken depending on your HTML or it could just cut off after a certain point.

Yahoo

Media queries
In previous years, Yahoo had this really annoying thing that it would apply any @media query styles you had in the email, regardless of the condition for which the @media query should be triggered. One of the available fixes around this annoyance was to use CSS selectors for all styles within the media query. That is no longer the case.


CSS comments breaking styles
I recently rediscovered this wonderful gem while working on a new fluid email for work. I had not built one before so I was providing plenty of comments in the CSS as well as using comments to provide section dividers for organization. Well, it turns out that Yahoo turns any CSS comment in the <head> styles into a CSS class trying to target something in the markup that doesn't exist. The worst part about it is that does not include the opening and closing curly braces with the newly created class callout. Because of that, the style that immediately follows the CSS comment will not apply because the browser thinks it is a CSS selector targeting a child of a non-existent parent. If you really want to have CSS comments and care about the email rendering as expected, you will need to add your own made up ID or class callout immediately following the CSS comment. See the following example:
/* CSS COMMENTS */
.yahooCSSCommentFix {}
.realTarget {
width:100px;
}

You can also take this Yahoo flaw and use it to your advantage. Since you know that any style that comes immediately after a CSS comment, you can use that to reset a style in every other client. So if you wanted Yahoo to load a specific background image, use a different font family or color, you would set that style first, then write a CSS comment and write the same style a second time but with the different values applied. Because Yahoo will break the second instance, it will use the style values from the first style but every other client will use the second one.

This section over at FreshInbox covers this issue in more detail if you want to read more on the subject.

iOS

Font sizes
iOS devices do not naturally like font sizes smaller than 12 pixels and if there are copy blocks set to have font sizes smaller than that, iOS will automatically change the font size to be about 12 pixels. This creates a problem for disclaimer type copy that uses small font sizes. The issue can be even greater if there is "line-height" applied as a style to the copy block because iOS will still adhere to that line-height value. So when it scales up the font sizes, it will potentially have muliple lines of copy running on top of each other. The fix for this is to include a small block of CSS in the <head> style section.

Below is the CSS code needed in the <style> tag in the <head> to keep iOS from adjusting the font size automatically and breaking the design.
* {
-webkit-text-size-adjust:none;
}


Additional padding
An issue specifically on iPads that probably started with iOS 6, is that the Apple Mail email app adds very large default padding to the left and right sides of the email pushing in the contents of the email. To fix this, clear out the default padding and margin for the entire email.
* {
margin-left:0px;
margin-top:0px;
margin-right:0px;
margin-bottom:0px;
padding-left:0px;
padding-top:0px;
padding-right:0px;
padding-bottom:0px;
}
Take note that other styles are needed in the catch all style from the example above, this is just the minimum needed to prevent the padding/margin issues with iOS. I have written out the long form of both margin and padding because one or two clients from years ago didn't like the shorthand version of margin and/or padding. I think Hotmail was one of them, which is irrlevant now being replaced by Outlook.com, but it doesn't hurt to use the long form, so I have just stuck with it since I know it works.


Background Images
One last iOS issue to be aware of is that it will not display background images that are larger than 3 megapixels (dimensions, not file size). The only time this would be an issue is on emails that have very wide backgrounds and need to be tall enough to not repeat (shouldn't be using repeat anyways because Outlook doesnt support it unless you are using media queries to apply). The image size would have to be, for example, greater than 1000x3000 in size. So it is very unlikely this will happen but if there is ever a sizable background image for the email, multiply the width of the image by its height and make sure that number is less than 3145728 (3 megapixels). This was last tested with iOS 6 or 7, so it may have been changed now with the newer devices and OS updates to support that, but just be aware that this might still be an issue.


Rendering issues
iOS 10+ — The latest versions of iOS Apple Mail changed the way it handles email auto-scaling. In some cases, this can cause issues with how the email looks, such as being off-center or scaled down. You can add padding:0; to the body styles (recommended anyway) or add the following meta tag snippet to the head:
<meta name="x-apple-disable-message-reformatting">
This fix comes from an Apple Mail engineer, so if it doesn't work for you, blame Apple.

Margin and divs

Margin should be avoided as a general rule. Outlook 2007+ will apply margin to <td> tags as extra padding. Every other client does not apply margin at all to <td> tags. Margin that is applied to images appears to work in all clients except Outlook 2007+ which seems to ignore it completely. From some recent (8/26/16) testing, divs seem to work as containers for copy in all clients and can have a whole host of styles applied (font-family, font-size, font-weight, font-style, line-height, color, background-color, width, float, padding, margin, border-radius, border, and text-transform) that work across the board except for Outlook app. Outlook 2007+ does not support float, width, padding, or border-radius.

Background images

In order to have background images work, you need to use three different methods to make sure it works in almost every client. The first two are the easy ones: setting the background attribute on the <td> tag and setting the background-image style on the same <td> tag. If you care about Outlook 2007 and up for Windows OSes, you will need to use special VML markup in order to have a background image appear. See the example below:
<td align="center" background="images/bkg.jpg" style="background-image:url('images/bkg.jpg');">
<!--[if gte mso 9]>
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:500px; height:200px;">
<v:fill type="frame" src="images/bkg.jpg" color="#ffffff" />
<v:textbox inset="0,0,0,0">
<![endif]-->

<img src="alphaLogoGraphic.png" width="500" height="200" alt="" border="0" style="border:none; display:block;" />
<!--[if gte mso 9]>
</v:textbox>
</v:rect>
<![endif]-->
</td>
Note: Example with copy instead of an image within the background column coming soon, but this gist of it comes down to having a table with width/height values that are equal to the background image width/height, the copy has valign="top" and it just fills the space of the table where it can. Since valign="middle" is not supported on Outlook 2007+, you can't have vertical alignment of the copy within the space. Stupid Outlook.

So now for the downsides with VML markup for background images. It must be made to fit an exact area with the width and height values set on the <v:rect> tag. If you don't have both of those values set, the box area will be as big as the content and the background image will only fill that same space. So depending on what kind of background image you have and the content that is sitting on top of it, you will need to have a decent amount of buffer space built into the background image so copy has room to grow/fill when it comes to line-height rendering differences between clients. Another thing to be aware of is that if you set a width and height on the <v:rect>, it will crop off anything that extends out of the box area.

One last issue to be aware of with background images is that Gmail app on Android doesn't display background images if it is not a Gmail email account.

Phone numbers and addresses

You probably know about the Apple meta tag that can be included in the <head> that prevents it from being a link. For emails that typically isn't advised as that would break expected functionality from iOS users. There are several different solutions to handle the style of automatically generated links from the OS. The first part is a style in the <head> that covers the styling of phone numbers and addresses in iOS. Example below:
a[x-apple-data-detectors], a[href^="x-apple-data-detectors"], a[href^="tel"], a[href^="callto"], a[href^="sms"], a[href^="webcal"], a[href^="maps"] {
text-decoration:none !important;
color:inherit !important;
}
This series of styles are utilizing CSS3 selectors in order to find any anchor tag whose href attribute value begins with any of those strings. All of those different selectors should cover off on any anchor that gets generated by the client automatically. Now this primary only covers styling in iOS, but it also covers Windows 7 Mobile (according to Litmus from when I was still using Litmus vs Email on Acid over a year ago). In the case of this example, it assumes that only the font color and an underline are being applied with the client-made anchor tag. To reverse that effect, it simply says to inherit the color from the parent element and to not have an underline.

The desktop Outlook app starting with 2007 and higher still styles phone numbers as links and so does Gmail. You probably don't care about Outlook since it is the bane of all email developers, but I imagine you do care about Gmail. The following example covers off on how to get a phone number to not be styled in either Outlook or Gmail.
<span style="color:#000000; text-decoration:none;"><a style="color:#000000; text-decoration:none;">1-800-555-9876</a></span>
The above example covers off on Outlook 2007+, Gmail, and possibly other clients that force their unwanted styles onto your designs. The nice thing about this trick is that because the anchor tag doesn't contain an "href" attribute, the automatically generated phone number link still works. Now, the thing to keep in mind with this example is that the <span> tag is required to be the outer most tag with the anchor being directly around the phone number. The <span> covers off on Outlook and the anchor covers Gmail, but if you change the order, it will break and still have blue font color and underlines attached to it.

Stacking tables

When it comes to building emails that can work well for both mobile and desktop, you might want to have a design that features two or three column layouts for desktop, but be a one column layout on mobile. To accomplish this and have it work across all clients, several things are required. Below are all the required actions including steps for ensuring that Outlook app for Windows behaves.

  1. Create a class to be placed in a media query style in the <head> styles that will reset the width of your table columns to be the full width of the parent table.
  2. Create an Outlook only style tag that will be paired with Outlook comments. More on this later.
  3. The <td> that will hold the multiple tables needs to have the width attribute and width, min-width, max-width styles applied to it with the same value as the parent <table>. The <td> should also have align="left" applied to account for Apple Mail 5 and Outlook 2011 running on Mac OS X 10.7 Lion. If the left alignment is not set, the tables will stack for desktop in those (probably used by two people) clients.
  4. Each table that gets created to be a column should have the following set along with other expected attributes for tables: align="left", width="Y=(parentTableWidth / numColumns)", class="mobile_width_600", style="width:Ypx; min-width:Ypx; max-width:Ypx; display:block;". The display:block style is used to cover off on older versions of Firefox.
  5. Add an Outlook-only comment in between each table that adds <td> tags to get around Outlook adding space when there are multiple tables side-by-side.

Now let's dive into each step. The following set of examples will assume a content width of 600 pixels and that there are two "columns" to be shown.

First we have to create the width reset class for mobile devices. Featured is the media query I use for emails to cover off on iOS and stock Android email clients. Also being used is the CSS selector that, in this example, finds all tables with a class attribute thats value is set to "mobile_width_600" and applies the new width to it. The "!important" part is required to overrule the inline style.
@media only screen and (min-device-width:240px) and (max-device-width:710px) {
.mobile_width_600 {
width:600px !important;
min-width:600px !important;
max-width:600px !important;
}
}
Next up, if you care about Outlook anyway, are the Outlook only styles. Here we will be creating a brand new <style> tag surrounded with an HTML comment that Outlook will recognize as markup to insert and apply.
<!--[if mso]>
<style type="text/css">
#outlookColumn {
width:300px !important;
}
</style>
<![endif]-->
Now we are coming to the actual content area of the email. In the next example, we will have a full width table containing a full width column with an id attribute value of "outlookColumn" referencing the previous example's Outlook id style change. This is because we will have another Outlook comment between the two tables that wraps both the content tables with td tags to make the two "column" layout an actual two column layout for Outlook to avoid the issue of Outlook 2007 and higher adding 3 pixels of padding when two tables are placed side-by-side in the markup. Making further considerations for Outlook, valign="top" will be applied to ensure the columns will be matched in layout positions. This can be changed of course, but because every other desktop client will actually be using tables as columns, you can't guarantee any vertical alignment other than "top" unless you add a height value to the tables and the inner columns. Following previous best practices mentioned, width attributes and styles will be applied to cover off on both Gmail's and Outlook's rendering issues.
<table border="0" cellpadding="0" cellspacing="0" width="600" style="width:600px; min-width:600px; max-width:600px;">
<tr>
<td id="outlookColumn" align="left" valign="top" width="600" style="width:600px; min-width:600px; max-width:600px;">
<table align="left" border="0" cellpadding="0" cellspacing="0" width="300" class="mobile_width_600" style="width:300px; min-width:300px; max-width:300px; display:block;">
<tr>
<td align="center">
Left/top column content goes here
</td>
</tr>
</table>
<!--[if mso]></td><td align="left" valign="top" width="300"><![endif]-->
<table align="left" border="0" cellpadding="0" cellspacing="0" width="300" class="mobile_width_600" style="width:300px; min-width:300px; max-width:300px; display:block;">
<tr>
<td align="center">
Right/bottom column content goes here
</td>
</tr>
</table>
</td>
<tr>
</table>
Now if you want to get clever and have left column desktop be the bottom column on mobile, you can. You just need to flip the tables so that the "left" column table comes second in the markup and has align="left". Then the "right" table, written first in the markup, has align="right" set on the table. When the tables have enough space to sit side-by-side, they will honor the alignment regardless of the order they are written in, but when there is not enough space for both tables that causes them to stack, they will stack in order they are written in the markup.

Sadly the one downside to this is that you have to remove the Outlook comment in between the two tables as well as the id="outlookColumn" from the containing column, otherwise the two tables will still have the first table written be on the left. Because of having to remove the Outlook-only markup and styles, you have to worry about Outlook adding 3 pixels of invisible space between the two tables. So if you care about Outlook correctly displaying the layout like every other client, you will need to reduce the size of the tables by at least 3 pixels between the two. The following example will take two pixels off each table.
<table border="0" cellpadding="0" cellspacing="0" width="600" style="width:600px; min-width:600px; max-width:600px;">
<tr>
<td align="left" valign="top" width="600" style="width:600px; min-width:600px; max-width:600px;">
<table align="right" border="0" cellpadding="0" cellspacing="0" width="298" class="mobile_width_600" style="width:298px; min-width:298px; max-width:298px; display:block;">
<tr>
<td align="center">
Right/top column content goes here
</td>
</tr>
</table>
<table align="left" border="0" cellpadding="0" cellspacing="0" width="298" class="mobile_width_600" style="width:298px; min-width:298px; max-width:298px; display:block;">
<tr>
<td align="center">
Left/bottom column content goes here
</td>
</tr>
</table>
</td>
<tr>
</table>

Stacking images

If you don't want to get fancy with having stacking tables between desktop and mobile, you can do the same thing with images. All that is required is setting align="left" on each image and that the <td> tag containing the images also has align="left" as well as the width attribute and styles set on it. Example below:
<td align="left" width="600" style="width:600px; min-width:600px; max-width:600px;">
<img src="image1.jpg" width="300" height="200" alt="first" border="0" align="left" style="border:none; display:block;" />
<img src="image2.jpg" width="300" height="200" alt="second" border="0" align="left" style="border:none; display:block;" />
</td>
The "min" and "max" width styles on the column are for counteracting the render quirks of Gmail.

Viewport

You probably know about the <meta> tag used with iOS that sets the size of the viewport for the web site being viewed. Now when it comes to emails, the viewport doesn't do anything or matter because the iOS Apple Mail email client just renders emails to fit the width of the screen. But if you are going to have a "View in browser" version of your email, then you have to worry about how the email will render in the iOS Safari web browser. Here is where the viewport does matter and can make a difference. The following example is what I find works best for rendering emails so that it fits the full width of the screen.
<meta name="viewport" content="width=640" />
Note: The above example assumes that the content area of your email is 640 pixels in width. If it is more or less than that amount, it should be changed to match your email's content width.