October 29, 2020

Dark Mode Images

A bitmap image is one of the things you may not immediately think of when writing CSS and HTML for dark mode. Unlike an SVG, you cannot simply change the colours of the shapes in a bitmap image with CSS by specifying what colours you want them to be. And the approach you would take to handle a bitmap image in dark mode can vary depending on the type of image and the environment you are working in (e.g. web page vs html email).

Here is a quick look at some of the approaches and how you may implement them for web pages and HTML emails.

1. Using different images

Web

On the web you can rely on the <picture> element for this without writing additional CSS:

<picture>
    <source srcset="image-dark-mode.jpg" media="(prefers-color-scheme: dark)">
    <img src="image.jpg" alt="" />
</picture>

This approach works if you only serve a dark theme when the user's browser or operating system is set to dark mode. If you provide toggable dark/light themes from within the website, you would implement this differently (e.g. hide/display 2 different <img>s).

Email

The <picture> element is not widely supported in email clients at the time of writing, so you would hide/display 2 different <img>s with a media query. Litmus's The Ultimate Guide to Dark Mode for Email Marketers covers this approach well and goes further to explain how to use the [data-ogsc] attribute selector to target Outlook web and mobile app.


2. Using dark-mode-optimised images

If you do not wish to use different versions of an image (one for light mode and another for dark mode), in some cases you can optimise an image so it looks well on dark mode. You may use a transparent background and/or add outlines or light-coloured shadows that do not show on light mode.

⚠️ Transparent backgrounds

PNG is probably the most commonly-used image format when a transparent background is needed. The type of the image impacts the file size. When it comes to PNGs, a photograph for instance can be extremely large in size in comparison to other formats such as JPG and WebP. So do not disregard performance here.

Web

For simple shapes like circles and rectangles with rounded corners you can rely on CSS instead of using a large PNG.

For more complex shapes, you may be able to use clip-path, but not all its features are supported across major browsers at the time of writing.

Email

For simple shapes like circles and rectangles with rounded corners you can also rely on CSS instead in HTML emails.

But Outlook Windows and Windows Mail do not support border-radius

You can use border-radius as a progressive enhancement so your email would still look presentable in email clients where it doesn't work. If you must have those rounded corners or circles on Outlook Windows, you can use a VML fallback. VML has a number of predefined shapes such as <v:oval> and <v:roundrect> so it is not a huge amount of extra code:

<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" style="width:400px; height:200px;" arcsize="3%">
    <v:imagedata src="https://example.com/image.jpg" />
</v:roundrect>

3. Inverting colours

If you have images with white/light background and a black/dark foreground, inverting the colours with CSS's filter property can be an option:

@media(prefers-color-scheme: dark) {
    .dark-scheme--invert {
        filter: invert(1);
    }
}

On top of that it may make sense to use the mix-blend-mode property in some cases to blend in the image's background with the page's background if it does not match your dark mode background 100%:

@media(prefers-color-scheme: dark) {
    .dark-scheme--invert {
        filter: invert(1);
        mix-blend-mode: screen;
    }
}

See the Pen Invert image colours by Hussein Al Hammad (@hus_hmd) on CodePen.

Email

The prefers-color-scheme media query does not work in all email clients. Neither does the filter property. It is a nice progressive enhancement nonetheless.