October 1, 2021
What to consider when testing CSS features in email
It's no secret that support of various CSS features is fragmented and widely inconsistent. But have you thought about what it takes in order to confidently say a feature is supported in an email client?
Let's go through the various technical aspects you need to consider when testing CSS in email.
Let's start with the easy one. Most email clients rely on a browser to render HTML. This is obvious when it comes to webmail clients you access via a browser, but it is also true to native apps as they rely on browser engines to render the HTML. The exception here is Outlook Windows apps and Windows Mail as they use Microsoft Word to render the HTML.
Given browsers support for CSS features is not identical, the first factor we must consider when testing a CSS feature on email clients is whether browsers support it.
This is an important factor. On iOS, for instance, all native apps have no option but to use the same browser engine (WebKit) to render HTML. So up until iOS 14, no email client on iOS supported WebP images.
I am excluding Outlook Windows and Windows Mail apps from the rest of this article on purpose. Testing CSS features on email clients that use modern browser engines (which follow documented open standards) is one thing, and testing features on email clients that use proprietary software (which support a small set of HTML 4 features) is another thing.
What "support" means
So if the browser engine used by an email client supports certain CSS features, why do we need to look at whether that email client supports it too? How can they not support a feature if the browser engine they use support it?
Just because Chrome supports a CSS property, it does not mean a webmail client running on Chrome supports it. CSS declarations in HTML emails can be:
- stripped out
- the CSS declaration is kept, but is overwritten by email client's own CSS
- the CSS declaration is kept, but the email client's own CSS affects how the CSS property behaves
- the CSS property is kept, but the value is changed
- the value is kept, but the property is changed
And no, email clients do not document any of that.
Broad questions are rarely helpful in the context of email clients. A question like "is flexbox/grid supported in email clients?" has no short answer.
Flexbox/grid are CSS layout modules. Figuring out whether the module is supported in a browser is fairly straightforward. But you cannot check whether a whole CSS layout module is supported in email clients as easily despite the support summary below:
The above summary tell us two things only: whether the CSS property
display is supported and whether it can take the value of
flex. Nothing more. It doesn't mean the flexbox layout module is fully supported.
So what sort of narrower questions can we ask?
Testing whether a CSS property is supported is a good first step.
Gmail does not support the align-items CSS property. It completely removes it. So the following:
1<div style="display:flex; align-items:center;"></div>
And Yahoo does not support the height CSS property. It keeps the value, but renames the property to
min-height. So the following:
And testing the property on different elements could be insightful. For instance, Outlook mobile apps support the border-radius CSS property, but their default CSS styles prevent border-radius from working on tables.
CSS properties shorthand
Email clients may also have different support for shorthand properties and the separate properties that can be set by a given shorthand property. The background CSS property is an example of this.
CSS properties are only half of the equation.
In a CSS declaration there is a CSS property and a CSS value. An email client may support a CSS property while not supporting all valid values the property accepts in the CSS spec.
How an email client handles an unsupported value varies. For example, with
vh values, Apple Mail on iOS 15 keeps the declaration, but rewrites values as
0. While, Outlook mobile apps strip a declaration entirely if it has a
<gradient> value type.
CSS value types
CSS has many value types (also known as "data types") such as
<image>. And there are some sort of sub-types like
<gradient> which is a special type of
<image>. CSS functional notations (such as
calc()) are technically value types too.
Multiple CSS properties can accept the same value types. An example is the
background-color properties as both accept
<color> values. And while
background-color are widely supported among email clients, not all
<color> values are.
Outlook.com, for example, supports the
rgb() functional notation, but does not support the
hsl() functional notation even though both are
background-image is another widely supported property only when the
url() functional notation is used. Support for other
<image> values is inconsistent.
CSS value syntax
A CSS value type can be written in more than one syntax. An email client may support a CSS value, but only in certain syntaxes.
rgb() functional notation as an example. While it is widely supported, not all email clients support the whitespace syntax:
1<div style="background-color: rgb(0 128 0);"></div>2<div style="background-color: rgb(0 128 0 / 1);"></div>
border-radius is a widely-supported property, but Yahoo does not support the slash notion for defining elliptical corners (using two radii):
1<div style="border-radius: 10% / 50%;"></div>2<div style="border-radius: 27% 73% 70% 30% / 30% 34% 66% 70%;"></div>
CSS value units
Another thing to consider is the value units. An email client may generally support a CSS property like
height which accepts
<length> values according to the CSS spec, but the email client may not necessarily accept all
<length> values. See: Apple Mail on iOS 15 renders
vh units as
You may know a CSS feature is not supported in an email client, but still choose to use it as an enhancement for other email clients that do. This is a very reasonable thing to do (see Progressive Enhancement).
However, it is important to check what an email client does when it encounters a CSS feature it doesn't support. Does it remove the whole CSS declaration? Does it rewrite the CSS property and/or value? Are there any side effects?
An example of a major side effect happens in Gmail. While Gmail supports the
rgb() functional notation, it does not like it when the value is written in whitespace syntax
rgb(0 0 0). When Gmail encounters this syntax in a
style attribute of an element, Gmail strips the whole attribute:
1<!-- This -->2<div style="background-color:rgb(0 0 0); padding:20px;"></div>34<!-- Turns into this -->5<div></div>
Guess what happens if you choose to include the whitespace syntax in your embedded CSS in a
<style> block. It won't settle for removing the CSS declaration that includes
rgb() with the whitespace syntax. It won't settle for the CSS ruleset where the value is used either. It removes the whole