Why HTML Email Looks Different in Every Client

« Blog · By

An HTML email gets built, checked in a browser, sent — and arrives at part of the audience as rubble: columns stacked instead of side by side, buttons without rounding, fonts substituted, background images gone. The reason is sobering: there is no standard for how a mail client must render HTML. Every one of them does it differently, and some do it very differently.

The main reason is called Word

The single largest cause is a decision from 2007. Outlook on Windows switched at that point from the Internet Explorer display component to the layout engine of Word.

Classic Outlook therefore renders email not with a browser engine but with what a word processor considers layout to be. Word knows tables and paragraphs extremely well. It does not know modern CSS — not badly, but not at all.

That accounts for almost everything that looks different in Outlook: no rounded corners, no background images via CSS, no media queries, no flexbox, no web fonts, and for animated images only the first frame.

Outlook(Windows) Gmail(web) AppleMail Thunder-bird Inline CSS on the element style block in the head Media queries Flexbox and grid Background image via CSS Web fonts border-radius Animated GIF full limited not supported
One column is the odd one out. Ignore it and you are building for three clients and against one — and that one sits on every desk in a great many companies.

The other differences

Gmail in the browser removes part of what sits in the message head and does not honour some properties because they would disturb the page layout — position and negative margins among them. Web fonts via @font-face are stripped.

Apple Mail uses the same engine as Safari and is by far the most generous client. Check only there and you will wrongly conclude your message is fine.

Thunderbird sits close to Firefox and is generous too, with limits on fonts loaded from the network.

Dark mode, the second fracture

Since most clients offer a dark presentation there is a second source of surprises — and it is nastier than the first, because it also hits well-built messages.

Clients go about it differently. Some leave the message untouched. Some swap only colours that were not explicitly set. And some invert the colours of the entire message, explicitly set ones included.

That produces the familiar picture: a dark logo on a background that was white a moment ago and is now black. Or text that would be legible if its colour had not been inverted while the background colour of the surrounding box was not.

The most reliable counter is unglamorous: give images a border that works in both modes, or ship them as PNG with a transparent background and set the colour behind them. And never use a text colour that is only legible against one particular background.

The rules that follow

  1. Lay out with tables. Not because it is elegant, but because <table> is the one thing every engine understands identically — Word included.
  2. Put CSS on the element, not in the head. A style attribute survives everywhere. A style block does not.
  3. One column, at most 600 pixels wide. That is the width Outlook's preview pane copes with, and on a phone it is the only sensible arrangement anyway.
  4. Buttons as a table cell with a background colour, not as a styled <a>. A link without rounding is still a link; a button without a surface is invisible.
  5. Alt text on every image. Many clients load images only after consent — until then the alt text is the whole message.
  6. Nothing important in the image alone. If the discount figure lives only in the banner, recipients with images off will never see it.
  7. Send a real plain-text part. It is not just for text clients; it also feeds into the judgement of whether a message looks like a campaign.

Test, do not hope

Rendering cannot be derived, only looked at. The route is unglamorous: for every client that occurs among your recipients, create an address and send the message there.

Short-lived addresses are practical for exactly this — one per client, one per round, without creating accounts. Through an API this can also be automated: create an address, send the message to it, fetch the received HTML part and compare it with what was sent. That does not show what the client makes of it — but it does show what was stripped on the way.