Making Emails React to Outlook.com’s Dark Mode
One thing I love about Outlook.com’s dark mode is the button to toggle between dark mode and light mode for a message. A simple and handy option to quickly change the look of an email. (And I’m excited that a similar button is coming to Firefox DevTools soon.)
One thing I hate about this, though, is that if you carefully coded a dark mode for your email using a @media (prefers-color-scheme:dark)
media query, that button might do nothing.
That’s because using @media
always targets the browser at its highest level. So if you define mobile styles in a @media (max-width:600px)
media query, but your email is displayed in a 500px wide preview pane in a webmail inside a 1280px wide browser window, none of those styles will apply.
And if your email is displayed in Outlook.com’s light mode preview pane, but your operating system is set up in dark mode, all of your dark mode styles will still apply. (The problem is very similar to using @supports
in an email.)
Here’s an example of such a “problematic” dark mode media query:
@media (prefers-color-scheme:dark) {
.email-background {
background-color: #423500 !important;
}
}
In my latest clients work, I tried to find a solution to this.
Excluding Outlook.com from Dark Mode Styles
The first step is to make sure that styles inside a @media (prefers-color-scheme:dark)
won’t apply in Outlook.com. Outlook.com prefixes class
and id
attributes in HTML and CSS with an x_
.
Using an attribute selector in CSS, we can detect if a class was prefixed by Outlook.com ([class^="x_"]
).
Combining this with a :not()
pseudo-class and we can now apply styles for an element whose class
attribute doesn’t start with x_
.
@media (prefers-color-scheme:dark) {
.email-background:not([class^="x_"]) {
background-color: #423500 !important;
}
}
Adding Outlook.com Dark Mode Specific Styles
The second step is to add back dark mode styles, but this time making them specific for Outlook.com only. This time, we’re going to take advantage of how Outlook.com alternates an email colors for its automatic dark mode.
When it sees an element that doesn’t have “valid contrast”, Outlook.com will fix it by changing either the element’s color
and background-color
in CSS or color
and bgcolor
attributes in HTML. What’s a “valid contrast”, you might ask? Well, per Outlook.com’s source code, it’s a color with at least a 4.5 contrast ratio compared to Outlook.com‘s dark background.
And when Outlook.com changes an element’s color, it will add a custom data attribute on said element to save the original color. There are four different possible attributes in total:
-
data-ogsc
(for “original style color”) -
data-ogac
(for “original attribute color”) -
data-ogsb
(for “original style background”) -
data-ogab
(for “original attribute background”)
Using once again an attribute selector, we can target when Outlook.com has changed an element’s color and apply our own custom styles. But because Outlook.com only supports attribute selector solo ([attr]
) or with an element selector (E[attr]
), we can not simply use a selector like .email-background[data-ogsb]
.
My prefered way to deal with this is to have a main element with a white background color (or any color that gets changed by Outlook.com). So then we can use the data-ogsb
applied to that main element to target any child element. Here’s an example:
[data-ogsb] .email-background {
background-color: #423500 !important;
}
Let There Be Light
And voilà! We now have an HTML email that reacts to Outlook.com’s own dark and light button.
Here’s the full code for the email above.
I’m aware that this technique might be a bit too hacky and not for every emails. My biggest fear is that this would ultimately remove support for Gmail (if Gmail were ever to support @media (prefers-color-scheme:dark)
as rumored almost a year ago).
But for now, I think I like it.