In the last two chapters we explored the basics of classic HTML and CSS. This tutorial post will help you to understand the fundamental differences between classical web HTML and email HTML.
The first time I encountered the concept of email HTML I was very surprised that I could not use script
s, I had to use table
s and I had to use inline style with the style
attribute. Besides these, most of the things that should have worked, just did not.
Coding HTML emails can be very frustrating. The main reason is that people just hear that they have to use ancient techniques, but they don't really know what they can use and what are actually myths.
Since the game changer announcement by Gmail - which says that they started to support the style
tag and media queries - I'm continuously thinking about that it's time to revisit the very basics of HTML emails. There might already be some email lists with subscribers only with modern email clients. It does not mean that you don't have to know how to support older email clients. In most of the cases you will have to support legacy email clients anyways.
In this chapter I would like to help you to understand the basics of modern HTML emails. By the time you will have finished this tutorial post you will be able to answer the following questions.
- Why can't we use javascript in our HTML emails?
- Why should we not use external stylesheets?
- Why and when should we use
table
s instead ofdiv
s? - Why and when should we use inline styles and attributes instead of classes?
We are going to build a one column layout email based on the first two chapters of this tutorial series. It means that we start from a classic web based HTML, and later we turn it into a proper HTML email.
I am going to show you the Litmus results after every step, so you can gain a better understanding of the effects of the actual steps on different email clients.
Components
If you take a look at the example, you might be able do differentiate four different components. By defining these components and having a clear picture of them, you will be able to adopt your code to new email clients very quickly. The logic of your template will remain the same, only the markup will change.
Besides that, you can set up your text editor in a way that it inserts the HTML snippets of your components for a certain user interaction. You can also use templating languages like ejs or even React. These techniques will speed up your workflow radically.
In this tutorial series I will not use these tools, so everybody will be able to finish the tutorial with a simple text editor and with a browser.
Centered Container Components
As you can see in the example preview the whole content is aligned to the middle of the page. Besides that, the most important property of the centered container is its width.
In our example the width of the container is 600 pixels. The reason is that it became a golden rule in email HTML as we wrote it in an article previously. Email clients are becoming better and better and screen resolutions bigger and bigger, so it sounds very timely to revisit this issue again. I will do it in a later post in this series.
Section Components
Sections are the colored stripes with the actual content in them. They stretch across their parent container. If you read the previous post, then you might remember that the colored sections were outside and the centered containers were in them.
The main properties of the sections are the followings:
- they stretch across their parent containers
- they can have a background color
- they can have a font color
- they can have padding
Text Components
As its name suggests it's an element type which contains textual data (eg.: <p>
, <h1>
, <h2>
...). In this framework text elements can have the following properties:
font-family
font-size
line-height
padding-bottom
padding-top
text-align
You might as why don't text elements have color
property. Well, I think that colors should be handled at the same place. So the background-color
and the color
properties should be applied at the very same place, and in our case it's the section component.
Image Components
In our example, an image component will be a simple img
tag, which width is surely less the mobile width. (It's 210px actually.) I've decided to do it in this way, so our example won't be too complex. We are going to publish a whole article about images later.
As you can see, these are very, very basic components, so we can keep things in this article relatively simple. In the upcoming posts, we are going to introduce new components, for example multi-columns or buttons.
After a while you will have a rich component library which will help you to create complex HTML emails which will look well on most of the email clients.
Building a One Column Layout HTML Email
We are going to start our email template in the way we have learnt during this tutorial so far. It means that we are going to build a classic HTML, just how we would build it for the web. This way I will be able to show you what works and what does not work in email HTML.
In the first few steps we are going to check out how far we can go without using tables. It means that firstly we will try to support all of the web clients (and the old Gmail app) before starting to support Outlooks.
Actually, there will be three distinct steps where I will show how you can support:
- Yahoo! Mail
- Email clients which strip the style tag (old Gmail app + Mail.ru in our case)
- Word based Outlooks
After discussing the three cases above, we are going to combine the solutions together, so our template will look great on every email client supported by Litmus. (Except Lotus Notes 7, but that will be acceptable as well.)
If you have a Litmus account, that's great, but I will publish the results of every step, so it's okay if you don't.
One Column Layout with Web HTML & CSS
Based on the first two lessons, it's very easy to create such a simple HTML you see on the previous preview, I simply reused the classes we created.
The section components are simple div
s with background and padding related classes. The centered container is a div
as well, with a width related class. The text and image related components are h1
, p
and img
tags.
<!DOCTYPE html>
<html>
<head>
<title>Simple One Column Layout</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" />
<link rel="stylesheet" href="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/defaults.css" />
<link rel="stylesheet" href="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/colors.css" />
<link rel="stylesheet" href="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/layout.css" />
<link rel="stylesheet" href="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/images.css" />
<link rel="stylesheet" href="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/spacings.css" />
<link rel="stylesheet" href="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/main.css">
</head>
<body>
<div class="container600">
<div class="sm-padding">
<div id="header" class="m-padding bg-white">
<img alt="" src="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/img/logo.png" />
</div>
<div id="content" class="m-padding bg-brown">
<h1>Confirm Registration</h1>
<p>
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness.
</p>
<a href="http://edmdesigner.com" class="m-padding-tb">Confirm</a>
</div>
<div id="footer" class="m-padding bg-gray">
<p>
2017 <script>document.write("@");</script> COPYRIGHT - EDMDESIGNER
</p>
</div>
</div>
</div>
</body>
</html>
As you can see above, it's a div
based HTML with external CSS files, multiple classes on elements and I even used script
tag to put print the @ sign in the footer.
You can check out the full source code of this step on Github.
If you take a look at the Litmus test results, you will see that there are some email clients which will display our email template beautifully.
On Apple clients (Apple Mail 10 above & iPhone below), the only thing what's missing is the @ sign from the footer. It has security reasons, most of the email clients ignore script
tags. It would be very easy to steal someone's session id if they open your email containing the malicious script
from a web mail environment (eg.: Gmail). So it's a very understandable restriction. Don't use script tags in your emails.
Whoops! As you can see below, there are some email clients which will interpret script tags. In this case it's Outlook 2000, but it's still not a reason to use script tags in emails. (There is the @ sign in the footer.)
It's very eye-catching that none of the formatting were applied. That is the case with lot of other email clients, for example Gmail:
And Gmail App...
I think it's obvious from the results that classic HTML and CSS that we got used to on the web won't work in emails.
Use the style
tag instead of external CSS
Many email clients don't support external CSS. To multiply the number of the supported clients, simply put all of the external CSS to a stlye
tag in your HTML.
<!DOCTYPE html>
<html>
<head>
<title>Simple One Column Layout</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<style>
/* defaults */
html, body, div, p, ul, ol, li, h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 0;
}
body {
font-size:10px;
line-height:10px;
}
h1, h2, h3, h4, h5, h6 {
font-family: Arial, sans-serif;
}
h1 {
font-size: 28px;
line-height: 32px;
margin-bottom: 24px;
}
h2 {
font-size: 24px;
line-height: 28px;
margin-bottom: 20px;
}
h3 {
font-size: 20px;
line-height: 24px;
margin-bottom: 16px;
}
p {
font-size: 16px;
line-height: 20px;
font-family: Georgia, Arial, sans-serif;
}
/* colors */
body {
background-color: #F4F4F4;
}
a {
color: #58585A;
}
.bg-white {
background-color: #FFFFFF;
color: #58585A;
}
.bg-brown {
background-color: #F8F7F0;
color: #58585A;
}
.bg-gray {
background-color: #58585A;
color: #FFFFFF;
}
/* images */
img {
width: 100%;
height: auto;
display: block;
margin: 0;
}
/* spacings */
.sm-padding {
padding: 10px;
}
.m-padding {
padding: 30px;
}
.m-padding-tb {
padding-top: 30px;
padding-bottom: 30px;
}
/* layout */
.container600 {
width: 600px;
margin: 0 auto;
}
@media all and (max-width: 599px) {
.container600 {
width: 100%;
}
}
/* main structure */
#header img {
width: 210px;
}
#content a {
display: block;
width: 100%;
font-size: 16px;
text-align: center;
}
#footer {
text-align: center;
}
</style>
</head>
<body>
<div class="container600">
<div class="sm-padding">
<div id="header" class="m-padding bg-white">
<img alt="" src="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/img/logo.png" />
</div>
<div id="content" class="m-padding bg-brown">
<h1>Confirm Registration</h1>
<p>
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness.
</p>
<a href="http://edmdesigner.com" class="m-padding-tb">Confirm</a>
</div>
<div id="footer" class="m-padding bg-gray">
<p>
2017 @ COPYRIGHT - EDMDESIGNER
</p>
</div>
</div>
</div>
</body>
</html>
If you compare the test results from the previous step and this step you will be amazed by the difference. By this simple modification, most of the web based email clients are already good to go.
AOL Mail is rendered perfectly (above), but the background color of the body is not applied on Gmail (below), Outlook.com and Office 365.
Besides the web clients, you might have noticed, that half of the Outlooks are also okay. Those are the ones with the IE rendering engine. The ones with the word rendering engine are going to drop most of the formatting from this template.
You can check out the full source code of this step on Github.
Use a wrapper container
To resolve the previously seen background color issue, you simply have to wrap your whole content to a wrapper container.
...
body {
background-color: #F4F4F4;
}
.wrapper {
background-color: #F4F4F4;
}
...
</style>
</head>
<body>
<div class="wrapper">
<div class="container600">
...
</div>
</div>
</body>
Gmail, Outlook.com and Office365 are fixed!
There are only two web based clients left. The first is Yahoo! Mail. I consider it as a separate topic and we are going to fix it in the next step.
The other problematic webmail is Mail.ru. Believe it or not, Mail.ru is very, very similar to the old Gmail app, because it strips the style
tag from the HTML. We are going to deal with this issue in a separate step.
Beside the webmail issues above, there is something very unusual you might have noticed. Yes, you guessed it well, it's related to the word based Outlooks. Look at the next two screenshots about Windows 10 Mail:
On the screenshot above from the previous step, there is no wrapper around the content. On the screenshot below from this step, there is!
So what can we conclude from this difference?
Well, even this family of Oulooks apply classes on elements, but only one.
How do I know that?
Take a look at the sections in our code. There are multiple classes on them, and the second is not applied.
Then why don't we see proper paddings on the sections?
Because word based Outlooks don't apply many, many properties on div
s. They ignore padding
s and width
s on div
s, but they apply background-color
and color
!
You can check out the full source code of this step on Github.
CSS Comments Mess Up Rendering on Yahoo! Mail
As I was trying to figure out how to fix the div
based HTML for Yahoo, I encountered unusual things. For example the width property did not work on my centered container. Even more extreme things happened... paddings were not applied for a certain div
but they were for other div
s.
Eventually I figured out that if there is a comment line in the CSS, then Yahoo! Mail won't define the next class. It's probably because of a parsing error.
So, for example the following class definition did not work:
/* layout */
.container600 {
width: 600px;
margin: 0 auto;
}
But when I removed all of the comment lines, then miracle has happened. Yahoo! Mail was fixed!
.container600 {
width: 600px;
margin: 0 auto;
}
UPDATE: Our Dark Mage of Email HTML - one of my co-founders, Greg - informed me that it's a well known issue in Yahoo! Mail.
You can check out the full source code of this step on Github.
Use Inline Style to Support Legacy Email Clients
There some email clients which strip the style
tag from the email. It means that no class definitions will be applied! The first example for this is Mail.ru:
The second example is old Gmail and old Android clients:
Gmail announced that they were going to support the style tag and media queries. Thanks to the update, HTML emails on Gmail Apps are very pretty already on many devices (although in this test, the image could not load...):
To fix legacy email clients which strip out the whole style tag, you must inline ALL of your CSS properties. But be very careful with this, because in many cases you might not need to do it.
Check your audience on your email list, and if there are not so many people reading your emails on legacy email clients, just stick to classes and don't inline anything.
<!DOCTYPE html>
<html>
<head>
<title>Simple One Column Layout</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<style>
html, body, div, p, ul, ol, li, h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 0;
}
body {
font-size:10px;
line-height:10px;
}
@media all and (max-width: 599px) {
.container600 {
width: 100%;
}
}
</style>
</head>
<body style="background-color:#F4F4F4;">
<div style="background-color:#F4F4F4;">
<div style="width:600px;margin:0 auto;">
<div style="padding: 10px;">
<div style="padding:30px; background-color:#FFFFFF;color:#58585A;">
<img alt="" src="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/step-00/img/logo.png" style="display:block;width:210px"/>
</div>
<div style="padding:30px; background-color:#F8F7F0;color:#58585A;">
<h1 style="font-size:28px;line-height:32px;margin-bottom:24px;">Confirm Registration</h1>
<p style="font-size:16px;line-height:20px;font-family: Georgia, Arial, sans-serif;">
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness.
</p>
<a href="http://edmdesigner.com" style="display:block;color:#58585A;font-size:16px;line-height:20px;font-family:Georgia,Arial,sans-serif; text-align:center;padding-top:30px;padding-bottom:30px;">Confirm</a>
</div>
<div style="padding:30px; background-color:#58585A;color:#FFFFFF;">
<p style="font-size:16px;line-height:20px;font-family: Georgia, Arial, sans-serif; text-align: center;">
2017 @ COPYRIGHT - EDMDESIGNER
</p>
</div>
</div>
</div>
</div>
</body>
</html>
By using inline styles, Mail.ru looks much better now:
As well as old Android clients:
You can check out the full source code of this step on Github.
Use Tables to Support Word Based Outlooks
In this section we take the code which fixed Yahoo! Mail. It means that we go back where we used classes, not inline style.
If you want to support word based Outlooks, you have to very, very careful. There are several things what you have to keep in mind.
The first is that the rendering engine of word does not support many properties on div
s. The most important css properties which are not supported on div
s are width
and padding
. Without them it would be impossible to define layouts. Luckily we can use them on td
s. That is why we have to use table
s. If you use tables, you have to set the cellpadding="0"
and cellspacing="0"
to avoid non-expected spacings.
The second is that you can use only one class on one HTML element. If you use multiple, then only the first will be applied.
The third thing is that you can't use complex selectors. You should stick to simple class definitions. For example the following will not be applied by word based Outlooks.
.bg-brown td {
background-color: #F8F7F0;
}
And the final one is that you have to use the <center>
tag to position your centered container in the middle of the screen. It means that you will also have to use text-align: left;
at some point.
Okay, it seems hard, but if you think in components it's not that complicated actually.
Let's start with the section component.
.section {
width: 100%;
min-width: 100%;
}
.bg-gray {
min-width: 100%;
background-color: #58585A;
color: #FFFFFF;
padding: 30px;
}
...
<table class="section" cellpadding="0" cellspacing="0">
<tr>
<td class="###CSSCLASS###">
###CONTENTS###
</td>
</tr>
</table>
In the markup above I indicated with ### pre- and postfixes where you can modify something. The ###CONTENTS### part is where you put the content of this component. An example for the ###CSSCLASS### is .bg-gray
. You can define similar classes. The rule number one is that you should only modify the background-color
, color
and padding
properties.
The centered container component is even simpler.
.container600 {
width: 600px;
}
.container-cell {
width: 100%;
text-align: left;
}
@media all and (max-width: 599px) {
.container600 {
width: 100%;
}
}
...
<center>
<table class="container600" cellpadding="0" cellspacing="0">
<tr>
<td class="container-cell">
###CONTENT###
</td>
</tr>
</table>
<center>
As you can see I used the center
tag to align the container. That is why I needed to add text-align: left;
to the .container-cell
.
The text and image components are simple HTML elements, there is not much I could talk about.
As you can see, by obeying the simple rules I talked about previously, it's actually not that hard to create a robust email HTML which will support all of the Outlooks. You just have to combine the components we have defined.
Besides that you should include some CSS resets to your style tag. I used some of Julie Ng's CSS resets, who is a recognised email designer.
The whole source code of the template looks like this:
<!DOCTYPE html>
<html>
<head>
<title>One column layout</title>
<style>
html,
body,
table,
tbody,
tr,
td,
div,
p,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
font-size: 0;
line-height: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-spacing: 0;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
td {
border-collapse: collapse;
}
img {
-ms-interpolation-mode: bicubic;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: Arial;
}
h1 {
font-size: 28px;
line-height: 32px;
padding-top: 10px;
padding-bottom: 24px;
}
h2 {
font-size: 24px;
line-height: 28px;
padding-top: 10px;
padding-bottom: 20px;
}
h3 {
font-size: 20px;
line-height: 24px;
padding-top: 10px;
padding-bottom: 16px;
}
p {
font-size: 16px;
line-height: 20px;
font-family: Georgia, Arial, sans-serif;
}
a {
color: #58585A;
}
img {
width: 210px;
}
.section {
width: 100%;
min-width: 100%;
}
.bg-white {
min-width: 100%;
background-color: #FFFFFF;
color: #58585A;
padding: 30px;
}
.bg-brown {
min-width: 100%;
background-color: #F8F7F0;
color: #58585A;
padding: 30px;
}
.bg-gray {
min-width: 100%;
background-color: #58585A;
color: #FFFFFF;
padding: 30px;
}
.bg-light-gray {
background-color: #F4F4F4;
}
.bg-none {
min-width: 100%;
padding: 30px;
}
.container600 {
width: 600px;
}
.container-cell {
width: 100%;
text-align: left;
}
@media all and (max-width: 599px) {
.container600 {
width: 100%;
}
}
</style>
</head>
<body style="background-color:#F4F4F4;">
<table class="section" cellpadding="0" cellspacing="0">
<tr>
<td class="bg-light-gray">
<center>
<table class="container600" cellpadding="0" cellspacing="0">
<tr>
<td class="container-cell">
<table class="section" cellpadding="0" cellspacing="0">
<tr>
<td class="bg-white">
<img alt="" src="https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/img/logo.png"/>
</td>
</tr>
</table>
<table class="section" cellpadding="0" cellspacing="0">
<tr>
<td class="bg-brown">
<h1>Confirm Registration</h1>
<p>But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the
master-builder of human happiness.</p>
<table class="section">
<tr>
<td class="bg-none">
<p style="text-align:center;">
<a href="http://edmdesigner.com">Confirm</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="section" cellpadding="0" cellspacing="0">
<tr>
<td class="bg-gray">
<p style="text-align:center;">2017 @ COPYRIGHT - EDMDESIGNER</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</center>
</td>
</tr>
</table>
</body>
</html>
As you can see from the Litmus results and from the screenshot below, the template looks great on all of the Outlooks.
You can check out the full source code of this step on Github.
Supporting All of the Email Clients
(Except Lotus Notes 7. :D - Although in the end that will be acceptable as well.)
So as we saw we can support all of the Outlooks if we use tables, with only one class per HTML element. We could create all of our components.
Unfortunately there are some email clients which don't fully support some properties defined in classes and applied to tables
s. An example for this issue is Comcast:
Lotus Notes 8.5 is very similar. With div
s and classes, it worked perfectly. But with tables
and classes, it just messes up our design. (IBM Notes 9 works in the exact same way.)
Not to mention old Android clients and old Gmail clients, where you have to inline everything.
So the idea is to inline as much as we can. For text elements it's easy, because we have to inline each and every property.
For our components it's a little bit more complicated. Let's see how the section component looks like:
<table width="100%" cellpadding="0" cellspacing="0" style="min-width:100%;">
<tr>
<td width="100%" style="min-width:100%;background-color:###BACKGROUNDCOLOR###;color:###FONTCOLOR###;padding:###PADDING###px;">
###CONTENT###
</td>
</tr>
</table>
All of the properties which should be defined on the section level is on the td
of the table
above. We don't even need to use classes for this.
You might have noticed that besides width: 100%
I used min-width: 100%;
. You need to do it if you want your sections to be 100% wide on old Gmails. What a lovely trick.
The container looks like the following:
<style>
@media all and (max-width: 599px) {
.container600 {
width: 100%;
}
}
</style>
...
<center>
<table class="container600" cellpadding="0" cellspacing="0" width="600" style="margin: 0 auto;">
<tr>
<td width="100%" style="text-align: left;">
###CONTENT###
</td>
</tr>
</table>
</center>
Since we use the class called .container600
, email clients which support media queries and where the device width is less than 600 pixels, the container will turn into 100% wide instead of the original 600 pixels width.
If you check out the Litmus results you can see that this method performs very well on all of the email clients. We did not even have to use conditional ifs and other hacks. The only email client where our template is not very pretty is Lotus Notes 7, but to be honest, I am very satisfied with the results.
I selected some of the previews to illustrate that this method pretty well even on the most problematic email clients:
Lotus Notes 8.5:
Outlook 2013:
Android 5:
Mail.ru:
You can check out the full source code of this step on Github.
Summary & Conclusion
You have reached to the end of this tutorial post. If you have followed all of the steps, then you have learnt how to build a one column robust HTML email, which looks nice on all of the relevant email clients.
You have also learnt that why do you have to use tables, why you have to inline your CSS and why you should not use scripts and external CSS.
Hopefully you have realized that thinking patterns and components helps you a lot in coding HTML emails. The two most important components we defined in this post are the section and the centered container. The other two were the text component and the image component.
By the end of this lesson, our components became very robust. Combining them helps you create one column HTML emails which will be rendered properly on most of the devices and email clients.
In the next chapter, we are going to investigate how to build multi-column layouts that will stack on small screens.
Stay tuned!