COBOL is a computer language developed in the late 1950s. They wrote a bunch of banking software on it then somehow ... it never got replaced (IT projects are hard). So today, if you know COBOL, two things are certain:
- You are old. So old.
- You can basically charge whatever you like as a freelancer.
In the late 1990s, I learned HTML. It was a godless time. CSS wasn't invented. Layout was done with tables. 30kB was considered hefty.
I've got all kinds of obsolete tricks locked away in my noggin. Using them, I could build a site which would work in IE4 or Netscape Navigator 4.7. So the question is this: are these skills at all useful?
Yes.
Can I command a high price for them?
No.
Am I going to tell you about them now, in case you might find them useful?
Yes (sorry).
Wait, why are we doing this?
HTML emails. For a couple of reasons, HTML emails require you to party like it's 1999.
Reason one: bloody Microsoft
Many modern versions of Outlook use the HTML rendering engine of IE7, IE8 or even Microsoft Word(!). But while IE7 and IE8 did support CSS, let's just pretend they didn't. For the sake of argument.
What you might think now is but Microsoft replaced Outlook Express years ago with Mail
. This is true. Unfortunately, the HTML rendering engine seems to be exactly the same.
Reason two: health and safety
I dunno if you've heard this, but The Internet is a dreadful place. One can't help a simple man liberate his inheritance from a bank account without somehow handing over the keys to one's own savings. Email is the platform where many of these scammers practice their art. As a result, most reputable email services will put all your mail through some form of pre-processing. All JavaScript will be removed. Images may be blocked. External CSS and typefaces will be ignored. And in some cases, even CSS added within the head
of the document (and even as style
attributes) will be stripped out.
This limits the techniques we can use to a tiny subset of the kinds of things we used to do in the 1990s.
But surely, it can't be that bad, can it?
What you might be thinking right now is hasn't this berk heard of progressive enhancement?
to which I'd be forced to answer yes, but I had to Google it first, for an exact definition
. Unfortunately, Outlook still has a huge chunk of the email market. Unless you're 100% sure all your users have iPhones, it's probably worth your while using Ye Olde HTML. This means it'll work in Outlook but also on more modern web browsers. Because if support for obsolete HTML was dropped, how could modern eyes be expected to enjoy delights such as the Space Jam website or keep up to date on how Bob Dole is doing in his election bid?
Unsurprisingly, the relative simplicity of pre-CSS HTML also lends itself to a pretty compressed file, unless you use one of those frameworks, which lets you write modern markup, then converts it into hundreds of nested tables, with inline CSS up the wazoo.
But we are web devs. Let's create this from scratch.
Page structure
All HTML email layout should be achieved with tables. Some of you might not even be old enough to realise what a controversial statement that is. If you are this young, imagine I said why should we use React? jQuery does the same job
. Tables can offer many of the advantages of CSS Grid, but with fewer features plus a free look of horror from your web developer colleagues. However, tables are an ancient technology which works.
Congratulations. We have reached the lowest-common denominator.
Tables don't just allow us to produce multiple columns. They're also the only reliably method to change background colours (other than the body
tag).
Let's start with a simple table:
<table width="500" bgcolor="OldLace" align="center">
<tr>
<td>I am content</td>
</td>
</table>
This is your hello world
of HTML emails. That align
attribute aligns the whole table to the centre. If you added the same attribute to a table cell, it would align the contents within that table cell to the centre.
Here's some table tricks, to get you started:
But tables are more useful than for mere grids. They're the only way (aside from the body tag itself) to add background colours to text. Here's some tricks you can use:
Borders around tables require a Codepen all of their own:
Now some good news:
I hereby grant you permission to ignore pixel-pushing
It is possible to pixel-push in HTML emails but doing so is kind of a waste of time. You can add an arbitrary space between two elements using a spacer gif - that is a single, pixel wide, clear gif. This can be stretched using the width
and height
attributes, until it takes up the required space.
The problem is that because many email clients block images by default, if you do this, you'll end up with white boxes scattered throughout your email, harshing your mellow, as we used to say in the 1990s. Also, there’s a chance that using any single-pixel gif will get your email flagged as Spam as it might be mistaken for a web beacon.
You could use the spacer
HTML element, but this was only ever supported by Netscape Navigator 4.7, so it won't do much good here. Even Thunderbird doesn't use that antique browser engine.
Probably the best method to introduce vertical space into your HTML emails is the simple br
tag. This means you need to think in terms of units of line height, rather than pixels.
There is one other method, but it only works on images. The hspace
and vspace
attributes allow you to add either horizontal or vertical space, in pixels, onto an individual image. Note that this will be added on both sides of the image, so will often push the image out of alignment.
Forget about block level elements
Because we'll be using font
tags willy-nilly, there's a couple of things you need to know about them:
- They're inline
- If you wrap them around a block-level tag, they usually† won't have any effect
† Exceptions: you can influence border-color
in tables by putting a font
tag around the whole table and setting a colour on it. But it'll impact the text colour inside the table cells too.
This means that this pattern won't change the typeface using within the paragraph:
font > p
... but this one will:
p > font
However, we won't need no paragraph tags where we're going. Here's the craptacular pattern we'll be using instead:
<font face="sans-serif" size="2">
<b>This is a <q>heading</q></b>
<br/>
This is a <q>paragraph</q>.
<br/><br/>
This is a new <q>paragraph</q>.</font>
I'll give you a moment, so your nausea can subside. Yes, I am using the q
tag as scare quotes
.
The reason for this horrible pattern is that we want to declare that big, long font
tag as few times as possible. But every time we have text inside a new block level element (such as a table cell), it will need to be added again. This is what we're trying to avoid:
<h2><font face="sans-serif">This is a heading
</font></h2>
<p><font face="sans-serif">This is a paragraph.
</font></p>
<p><font face="sans-serif">This is a new paragraph.
</font></p>
The other reason we tended to avoid heading tags in the 1990s was that they came with a big old margin which was impossible to change, until CSS arrived, like a golden saviour on a mighty steed.
Note that because we can only rely on typefaces which are installed on the user's local machine, we need to declare a font stack instead of using your modern font-face
nonsense. This means that a typical font
tag will look like this:
<font face="Arial, Helvetica Neue, Helvetica, sans-serif" size="2"></font>
Imagine hundreds of them cluttering up your markup.
If you're very old, you might remember the basefont
element. This pre-CSS tag's dream was that we'd just define the font stack we wanted once per page. I've tested it in thirty-three different email clients. It isn't parsed by any of them.
Responsive tricks
When you think of HTML emails, the image I need you to hold in your mind is a sports car pulling a wagon full of hay. Or a horse pulling a sports car. Doesn't matter. The important thing to remember is that some HTML email clients are very capable, and will parse all of your CSS. These tend to be on mobile devices, so we can use nice, modern tricks for them, while remembering the lumbering horse / cart which is holding us back.
Avoiding horizontal scroll
Let's say we use the following table structure:
<table width="500" align="center">
<tr>
<td>email contents go here</td>
</tr>
</table>
On mobile devices, we could ensure that the table isn't too wide by adding this rule:
@media (max-width: 500px) {
table {width: 100%;}
}
Any styles
added using HTML attributes (for example width="500"
) will be overruled by CSS.
Unfortunately, if you have to consider Outlook running on high DPI displays, one of the work-arounds is this:
<table width="500" align="center"
style="width:500px">
<tr>
<td>email contents go here</td>
</tr>
</table>
This means the CSS needs to be a bit extra:
@media (max-width: 500px) {
table {width: 100% !important;}
}
Note this could have knock-on effects, if you use a table which needs to have a natural
width within the mobile breakpoint.
Swapping images
One way to swap out one version of an image for a different one in mobile is to add both images in the markup. This means that the mobile image needs to be hidden in Outlook. This is what the markup looks like:
<table width="500" align="center">
<tr>
<td>
<img src="http://url.com/mobile.jpg"
width="1" height="1" alt=""
class="hidden-lg">
<img src="http://url.com/desktop.jpg"
width="300" height="200" alt=""
class="hidden-sm">
</td>
<td>Email content goes here</td>
</tr>
</table>
Note that the width
and height
attributes of the mobile image are set to 1. If you set them to zero, the browser tends to ignore them and display the image at its native size. This is the CSS which will swap the images:
@media (max-width: 500px) {
.visible-lg {
display: none;
}
.visible-sm {
height: auto;
max-width: 100%;
width: auto;
}
}
This technique could also be used to switch the markup order of the email in the mobile viewport (albeit in a way which requires duplicated HTML).
Linearising tables
Let's say you had the following markup, but you wanted it to be linear, on mobile:
<table width="500" align="center"
class="sm-totem">
<tr>
<th>Column one</th>
<td>Column two</td>
<td>Column three</td>
</tr>
</table>
You could achieve this with the following CSS:
@media (max-width: 500px) {
.sm-totem, .sm-totem tr,
.sm-totem th, .sm-totem td {
display: block;
}
}
This will stack the cells of the table on top of each other in a totem pole fashion.
Both these techniques can be seen below:
Tips and tricks
There's lots of patterns which can save some bytes, when writing antique HTML. For example:
Combining attributes on a parent element
<!-- Don't do this -->
<table>
<tr>
<td valign="top">Content which will wrap at
some point</td>
<td valign="top">Content</td>
<td valign="top">Content</td>
</tr>
</table>
<!-- Do this -->
<table>
<tr valign="top">
<td>Content which will wrap at some point</td>
<td>Content</td>
<td>Content</td>
</tr>
</table>
Removing placebo tables
<!-- This table does nothing and can be removed -->
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td>I am content</td>
</tr>
</table>
Declaring font
tags as few times as possible
<!-- This: -->
<font face="sans-serif" size="3"><strong>Heading
</strong></font>
<br>
<font face="sans-serif" size="2">Content</font>
<!-- ... could be expressed leaner like this: -->
<font face="sans-serif">
<font size="3"><b>Heading</b></font>
<br>
<font size="2">Content</font>
</font>
<!-- see also "i", rather than "em" -->
Using structural tags to get stuff for free
<!-- This: -->
<table cellpadding="20">
<tr>
<td align="center" bgcolor="AntiqueWhite">
<b>Heading</b>
</td>
<td align="left" bgcolor="SeaShell">
Content
</td>
</tr>
</table>
<!-- ... could also be achieved like this: -->
<table cellpadding="20">
<tr>
<th bgcolor="AntiqueWhite">Heading</th>
<td bgcolor="SeaShell">Content</td>
</tr>
</table>
Remember that by default, th
elements are aligned to the centre and bold. td
elements are aligned to the left.
Some obsolete tags are useful
<!-- This: -->
<table width="100%">
<tr>
<td align="center">Content</td>
</tr>
</table>
<!-- ... could be expressed like this: -->
<center>Content</center>
<!-- or: -->
<p align="center">Content</p>
The above example is only useful if no background colour is required. Or if one line of text needs to be centred inside a table cell where all the rest of the text is not.
<!-- This: -->
<font size="-1">Legal disclaimer</font>
<font size="+1">Shouty text</font>
<!-- ... could be done like this: -->
<small>Legal disclaimer</small>
<big>Shouty text</big>
Images
A few things about images:
- They don't need a
font
tag around them (unless you're trying to influence theirborder
colour) - Declare a
width
andheight
- many email clients will not load the image by default and you don't want your layout to collapse because of this - Fill in the
alt
attribute - some email clients will display this text in the image's stead
<!-- Don't do this: -->
<table cellpadding="20" bgcolor="white">
<tr>
<td>
<font face="sans-serif">
<img src="https://google.com/logo.png"
width="150" height="80" alt="Google"/>
</font>
</td>
</tr>
</table>
<!-- This is all that is required: -->
<table cellpadding="20" bgcolor="white">
<tr>
<td>
<img src="https://google.com/logo.png"
width="150" height="80" alt="Google"/>
</td>
</tr>
</table>
Top comments (2)
While I agree with a lot of this, there are ways around some of the hindering Outlook nightmares, we have just as many issues with gmail these days. I started coding for html emails in the early 00's and it was always part of my duties as a web designer and jr developer.. In recent years however I have come to realize there is an insane need for dedicated html email developers, mostly because of the Outlook and Gmail email issues that require developers to continue coding with tables, or ghost tables for Outlook, use of mso and/or vml code just to appease Outlook email clients. It's also frustrating when you have to warn the account managers that the spiffy design creative showed the client and they approved up before talking to the coder and knowing the client will be reviewing the email on an older Outlook email client, that they won't see the background image, or the animated gif, or the gradient, or the curved border radius boxes, but that their consumer base will most likely see all of those features because most of the consumer base are using their mobile phones are using Apple and Android devices or modern email clients on their computers... As for paying well... Years ago like I said i was paid as a designer or developer and had to do emails as well, I now make seriously more money an hour, remote only, and strictly only code html emails for nationwide clients.. And i've been approached by huge tech companies tech recruiters to fill their html email developer positions.. While there might be 40k React developers in a part of the country, their might be a handful who can code the custom highly designed html emails and make sure the email will look as it's designed, be accessibility, responsive, and dark mode across the 80 or so email clients that Emails on Acid or Litmus will help you test out.. I have suggested to several people who have struggled to land their first software front end jobs to make ends me take crash course Build Responsive Dark Mode Friendly HTML Email Templates on Udemy I forwarn them that the coding is backwards, but could provide some serious income and job security..
Fascinating insight, @epicurus13. I'm kinda glad that the quirky 1990s HTML niche has started paying more. Perhaps that should be my retirement plan, when I can't keep up with MVC developments any more. Although what you mentioned about the propitiatory Microsoft tech fills me with horror.