Dark Mode Images

A static nuxt website deploying to a AWS S3 bucket

If you implement dark mode color schemes the font colors and background are handled automatically but handling images is a challenge. Consider these three different images: the GitHub logo, the JAMStart logo, and the AWS logo.

Image Transparency Issues

GitHub LogoJAMStart logoAWS Logo

Switch the site color mode to 'dark' and the GitHub logo almost disappears, the JAMStart logo loses details, and the AWS logo has parts that are hard to see.

Transparency Issues

Images with transparency, such as .png, .gif, .svg files, may look good in one mode but not the other. Images without transparency, such as .jpg, .bmp, etc, will look the same in both modes, but will have no blending with the background.

.png Images

The GitHub logo is a black logo on a transparent background. It looks great on a light background but is almost invisible on a dark background. Further, it would look quite good if you could invert the colors so the black logo is a white logo on a dark background.

The JAMStart logo is a multi-color logo on a transparent background. It looks great on a light background but some details are lost on a dark background. The white text and flourishes are missing in dark mode.

.svg Images

The AWS logo is an .svg file, where the image is drawn with vectors instead of pixels and it has a transparent background. It has both black and orange elements. The black elements are hard to see on a dark background, but the orange elements are visible in both light and dark modes.

Dark Mode Image Handling

Here are some approaches to image handling for dark modes:

  1. Insure all images have no transparency and look good in all color schemes.
  2. Use CSS filters to adjust image appearance in dark mode.
  3. Use CSS to always set image background color to a light background color in all dark modes.

Convert to Non-Transparent

One approach is to convert images to a .jpg format which does not support transparency. This ensures that the image will look the same in both light and dark modes. However, this approach may not be ideal as it removes the ability for images to blend with the background, and may require re-creating images without transparency. - Pros: Simple to implement, no extra code, but image processing required. - Cons: May require re-creating images without transparency, may not look as good as images with transparency, may need to recheck and replace images for a new color schemes.

CSS Filters

CSS filters can make transparent images clearer in dark mode.

Invert Bright

More black and white images may benefit from having their colors inverted in dark mode to enhance visibility. You can use the CSS property

.dark .dark-invert-bright {
  filter: brightness(0) invert(1);
}

dark-invert-bright

GitHub LogoJAMStart logoAWS Logo

The dark mode dark-invert-bright class transforms images to black and white and inverts the colors. The AWS logo loses its orange and the JAMStart logo loses its reds.

Hue Rotate

More colorful images might improve with the filter: hue-rotate(180deg); to shift the colors of the image in dark mode.

.dark .dark-hue-rotate {
  filter: invert(1) hue-rotate(180deg);
}

dark-hue-rotate

GitHub LogoJAMStart logoAWS Logo

The dark mode dark-hue-rotate class transforms images and shifts the color pallet. The AWS logo orange is more reddish and the JAMStart logo shifts to a pinkish.

CSS background

Instead of filters, another approach is to set the light mode background color for images while in dark mode. Set the background-color to a light color and then set the background-blend-mode to lighten or screen to blend the image with the background in a way that enhances visibility in dark mode.

.dark .dark-light-background {
  background-color: #fff;         /* Light background color */
  background-blend-mode: lighten; /* Blend mode to enhance visibility */
}

dark-light-background

GitHub LogoJAMStart logoAWS Logo

The dark-light-background class gives a light mode background color when in dark mode. While images look the same they have a distinct square background in dark mode.

Global Solutions

If you have a lot of images that need to be adjusted for dark mode, you can set the class globally for all images, with a global CSS class with a img element selector, like this.

.dark .dark-invert-bright img {
  filter: brightness(0) invert(1);
}

.dark .dark-hue-rotate img {
  filter: invert(1) hue-rotate(180deg);
}

.dark .dark-light-background img {
  background-color: #fff;         /* Light background color */
  background-blend-mode: lighten; /* Blend mode to enhance visibility */
}

Per Image

As you may have noticed in the examples above, each logo looked better with a different CSS technique.

Different Classes Per Image

GitHub LogoJAMStart logoAWS Logo

GitHub logo with invert-bright, JAMStart logo with the light-background, and AWS logo with the hue-rotate

I personally prefer to set the class on a per image basis, so I can choose the best technique for each image. This also allows me to have some images that are not adjusted for dark mode, if they look good in both modes without adjustment.

Nuxt/Vue Implementation

To add these to a Vue.js or Nuxt.js application, put the classes in global styles section. In the app.vue <style> global block (without scoped) section or in a global CSS file that is imported into your application.

  1. Create the CSS file: Place your global stylesheet file in the assets directory. For example, you might create a file at ~/assets/css/main.css.
  2. Configure in nuxt.config.ts: Open your nuxt.config.ts (or nuxt.config.js) file and add the path to your CSS file within the css array.
// nuxt.config.ts

export default defineNuxtConfig({
  css: [
    '~/assets/css/main.css',
    // You can add more files or even external libraries here
  ],
})

Markdown Authoring

To add a class to a markdown element or text, surround the content in [] or []() and then add a {} section right behind with the class names using the dot . notation, i.e. for italic class use .italic. image specified in a markdown file, you can use the class attribute in the image syntax. For example:

Writing markdown for an image or just some text like this:

![GitHub Logo](/images/blog/dmimg/GitHubLogoSm.png){.dark-invert-bright}
[some text with info and italic class applied]{.info .italic}

produces html like this:

<img class="dark-invert-bright" src="/images/blog/dmimg/GitHubLogoSm.png">
<span class="info italic">some text with info and italic class applied</span>

And looks like this to the reader:

GitHub Logosome text with info and italic class applied

Conclusion

There are several approaches to handling images in dark mode, each with its own pros and cons. The best approach will depend on the specific images and design of your website. Experimenting with different techniques can help you find the best solution for your needs.