Making sense of Outlook’s rendering engine
In 2007, Apple introduced the first iPhone. The same year, Microsoft introduced Outlook 2007 on Windows and its brand new HTML and CSS rendering engine: Word. It makes a lot of sense from an authoring point of view. But let’s just say to keep things polite that Word is not very good at rendering HTML and CSS. And while Outlook on macOS, iOS or Android all use WebKit or Blink as a rendering engine, even the latest release on Windows (Outlook 2019) still uses Word. In 2007, the iPhone paved the way for a mobile future while Outlook doomed HTML emails to use deprecated code and weird quirks forever.
There are four things that will help us tame the beasts that are the Windows versions of Outlook (or The Outlooks, as I like to call them): tables, tables, tables and more tables. But also: conditional comments,
mso properties, and VML.
Let’s see each of those in more details.
The only official existing documentation about Word’s rendering is a 2006’s post from Microsoft explaining HTML and CSS Rendering Capabilities in Outlook 2007. But it’s still enough to comprehend how Word’s engine works and why we’re going to need tables.
Microsoft splits CSS properties into three categories:
background-color, text properties (
white-space), border shorthand properties (
border-collapse) and a few others.
text-indentand margin properties (
padding(as well as
padding-bottom) and border longhand properties (
And each of these categories will only apply to certain HTML elements:
<span>only support CORE properties.
<p>support both CORE and COREEXTENDED properties.
- All the other elements supported by Outlook (like
<li>, …) support CORE, COREEXTENDED and FULL properties.
This means that not only we are limited by Outlook’s own capabilities. (No
border-radius, for example.)
But more importantly, we must think about which element to use to apply certain styles. So if I have to define a
width or an
height on a generic container element, I will use a
<table>. If I need a
padding, I will also use a
And even then, The Outlooks support of CSS is sometimes quirky and different from Web standards. Here are three examples:
marginis somewhat supported,
autovalues are not supported. So the
margin:0 autowe’d use on the web to center a table won’t work. We’ll use the
- In a table row (
<tr>), the vertical padding on cells (
<td>) will be the biggest value of that row. So if we have a cell with
padding-top:10pxand another one with
padding-top:20px, both cells will have
background-coloris well supported, but contrary to web standards, colors “bleed” and apply through margins. It’s usually safer and more consistent to apply a
background-colorto a table.
To this day, The Outlooks on Windows are the sole reason we still use tables in HTML emails. Luckily, there are ways for us to only make those tables visible for Outlook, hiding them to more capable email clients and allowing us to use more semantic code.
Microsoft introduced conditional comments back in 1999 in Internet Explorer 5. The idea is clever: inside a regular HTML comment (
<!-- -->), you can code a condition that will make the rest of the content visible if fulfilled. Here’s an example:
<p>This is only visible in Internet Explorer.</p>
Conditional comments were removed starting Internet Explorer 10. But they’re still supported in all Windows versions of Outlook using Word’s rendering engine. Instead of using
IE as a condition, we’re going to use the
<p>This is only visible in Outlook 2007-2019 on Windows.</p>
We can also append a version number to target only a specific Outlook version. Note that the version number is the actual software version number (
14, …), not the commercial name (2007, 2010, …).
<!--[if mso 12]>
<p>This is Outlook 2007.</p>
<![endif]--><!--[if mso 14]>
<p>This is Outlook 2010.</p>
<![endif]--><!--[if mso 15]>
<p>This is Outlook 2013.</p>
<![endif]--><!--[if mso 16]>
<p>This is Outlook 2016. And 2019.</p>
Things got nice for a bit in 2016 because the version number (
16) actually matched the commercial name (2016). But unfortunately for us, Microsoft decided to keep that same version number for Outlook 2019, so both are indistinguishable now. Oh, and because superstition is a thing, there’s never been a version 13.
We can also use operators to create more complex conditions, like
gte (greater-than or equal) or
lte (less-than or equal).
<!--[if gte mso 9]>
<p>This is Outlook 2007 and above.</p>
Even though this example is extremely popular in code you can find online, I recommend to use the
[if mso] condition to target all Outlook versions using Word’s rendering engine.
Another operator I use is the NOT operator (
!) that lets us build content for everything but The Outlooks.
<p>This is everything but The Outlooks.</p>
Are conditional comments safe to use in HTML emails?
Well, the desktop webmail of the german provider T-Online.de renders content in conditional comments. So if that’s a concern for you, you can hack your way using an
[if false] conditional comment (that T-Online will still parse and show).
The Outlooks’ rendering engine also has a lot of proprietary properties, mostly recognizable thanks to the
mso- prefix. There are hundreds and hundreds of those, documented by Microsoft in a CHM file. (Jason Rodriguez has a great story on how to get to that file, but fortunately Stig Morten Myre has an online archive.)
One interesting point is that for most standards CSS properties, Microsoft has an equivalent proprietary version prefixed by
mso- and suffixed by
-alt. So let’s say you want to define a
padding value but only for the Outlooks, you can use the
<td style="mso-padding-alt:0 16px"></td>
Another thing is that some proprietary properties of Outlook can mimick their modern CSS equivalent. For example,
text-underline-color in Outlook is the same as
text-decoration-color in CSS. So if you want to apply a specific color to a text underline, you can use both properties:
text-underline-color: red; /* Outlook version */
text-decoration-color: red; /* Standard version for clients that supports it */
Another example is the property
mso-hide:all, which is equivalent to
display:none (to hide an element). (One difference worth noting is that
mso-hide:all won’t cascade to children tables. So if you want to hide a table and all the tables nested in it, you will need to repeat
mso-hide:all on every table.)
Stig Morten Myre has a great article explaining how to fix bugs with Outlook specific CSS, including tips on how to use
VML is Microsoft’s take on a vector graphics format from the late nineties, right before SVG came around. Just like SVG, you can draw content with markup code. For example, if we want to draw a red rectangle, we can use the
<v:rect> element and the following code:
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fillcolor="red" stroked="false" style="width:200px; height:100px;"></v:rect>
In order to use VML, we need to add the namespace declaration (
xmlns:v="urn:schemas-microsoft-com:vml"). It can either be repeated inline for each VML element we’ll use. Or it can be added on the
<html> element only once. And because VML will only work in The Outlooks, we’ll make sure to wrap it in a conditional comment. Here’s a full working example for our previous red rectangle.
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml">
<v:rect fillcolor="red" stroked="false" style="width:200px; height:100px;"></v:rect>
One thing that got me about VML at first is that the syntax is very permissive. Boolean attributes can either be
1. And VML can also be written lowercase, uppercase, camelcase, etc.
Of course we can do more exciting things than red rectangles. One way we can use VML is to fake properties unsupported by The Outlooks. For example: background images. If we want to show a background image on our
<body>, we can use the
<v:background> element. Here’s an example:
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml">
<body style="background:#e2ecb7 url(https://i.imgur.com/ftd0S2j.jpg);">
<v:fill type="tile" color="#e2ecb7" src="https://i.imgur.com/ftd0S2j.jpg"></v:fill>
Will Outlook on Windows ever be good?
The more I spend time with The Outlooks, the more I like to say that they’re not all bad. They’re just different. Using tables, conditional comments, proprietary properties and VML can be enough to work around most Outlook quirks. And even provide things that couldn’t be done elsewhere.
After the launch of Outlook 2007, the now defunct Email Standards Project launched a campaign to Fix Outlook which resulted in the Outlook team hanging a poster on their wall. And that was pretty much it.
In 2016, Litmus launched a partnership with Microsoft. It brought support for
max-width in Outlook 2019 and a different font fallback when using web fonts. And that was pretty much it.
We’ve made the decision to continue to use Word for creating e-mail messages because we believe it’s the best e-mail authoring experience around, with rich tools that our Word customers have enjoyed for over 25 years.
My take is that Outlook on Windows will die with Word’s rendering engine. As the world is moving away from desktop computers, Microsoft is pushing its webmail and its mobile apps (which are all very good in comparison). And even if Microsoft moved away from Word in the next iteration of Outlook on Windows, it will probably take a decade before all the previous versions are upgraded. (Microsoft is just ending support from Outlook 2010 this year, in 2020.) So The Outlooks and Word’s rendering engine will still be around in 2030, but hopefully with a very low market share.