Friday, July 18, 2008

Cross-E-mail Client HTML

I was a salty Java programmer who never really cared much for GUI development until recently when I joined an RIA (rich internet application) software company called Appcelerator. One of my tasks at work was to create a monthly newsletter for our community members. We have an amazing graphic designer here (Tyrus) who created a really cool layout for me and all I had to do was convert the image into HTML so that it could be rendered in people's email clients.

Twenty plus hours later I am still trying to figure out all of the quirks associated with rendering HTML in email clients. I thought that creating cross-browser web pages (IE, Firefox, Safari) was a challenge, but cross-email web pages are nearly impossible. It turns out that there is an entire community of people who spend countless hours identifying what works and doesn't through painstaking trial and error.

My newsletter design was to have a grey background color rounded corners and one of the corners was intentionally asymetric with an arm shooting out of it. Like this:

So I cut up the image into some component images that I planned to align with HTML background colors inside a table to provide a canvas on which to place my text.

Now the question was how do I emulate the background color shown in the image within my webpage so that I can enter the textual content of the email? I had lots of options here with tables, div tags, background images, background colors, styles, etc. So I chose one and went about building my webpage after an hour or two I had everything working in Firefox so I decided to test it in Internet Explorer. WHOA! Not even similar! I spent HOURS googling and tried dozens of "tips", but it turns out that most people posting tips just regurgitate what someone else had told them (which wasn't necessarily true).

I finally decided that the only way to truly understand what background color options I had was to conduct a test. So I built an HTML table with 6 different ways to color a cell to see what kinds of color changes and alignments resulted. I had also learned that Outlook has used Internet Explorer to render it's HTML until version 2007 when Microsoft decided to use MS-Word instead (so I had to add MS-Word/Outlook2007 to my testing). Here are the results:

Notice how Firefox renders all of them exactly the same. Perfect alignment and perfect color. IE screws up both the alignment and the color so that almost every one of them is different! And Outlook... god help Outlook. After about 5-6 hours of searching I finally found this post which highlighted the fact that in strict mode (as opposed to quirks mode) an image tag is displayed as an inline element which causes Internet Explorer to add 4 pixels of spacing below the image to account for descending letters like j,q,p, and y (nevermind this is an image and cannot actually have descending letters!). The solution was to add a style tag:

style="display: block"

And voila, the space at the bottom of the image in IE disappeared! Simple right? As Lee Corso would say, "not so fast my friend". When I rendered the image with the style attribute in Outlook2007 it added a 1 pixel border on the LEFT of the image! I finally solved that problem by duplicating the background color of the image inside the TD cell of the table which contained it. Like this:

After trying several other email clients and toying with this for hours I finally decided that the most cross-client solution to background colors was to use tables (styling every padding/spacing/margin attribute to zero and collapsing borders) and to set background color directly on TD elements. Image alignment required the tricks I describe above. Also note that recipients who use Gmail will not get the proper spacing if you use style="margin xxx" or style="height xxx" or style="width xxx". For gmail, you must specify height or width as a tag attribute instead of a style.

Now that I have figured all of this out... I hope to never utilize this knowledge again in my personal or professional life. However, just in case I am forced (kicking and screaming) to do this again, this blogpost will serve as my documentation of what actually worked. And who knows, maybe it will help someone else not spend 20+ hours pulling their hair out on these issues.