HTML Emails - the COBOL of the 1990s

rossangus

Ross Angus

Posted on January 2, 2020

HTML Emails - the COBOL of the 1990s

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:

  1. You are old. So old.
  2. 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:

  1. They're inline
  2. 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 their border colour)
  • Declare a width and height - 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>
💖 💪 🙅 🚩
rossangus
Ross Angus

Posted on January 2, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

HTML Emails - the COBOL of the 1990s
htmlemails HTML Emails - the COBOL of the 1990s

January 2, 2020