nray.dev home page

How to Automatically Switch Images for Dark and Light Mode

Avatar

If your images have separate light and dark mode versions, you can display the correct one automatically based on the website's current theme.

Rectangle with "change theme to see different image" text
Try changing this website's theme to dark mode or light mode to see a different image displayed here.

There are two common ways to handle theme-based image switching on websites:

1. Switch image based on the system theme

If your website only supports the system's theme setting, you can use the prefers-color-scheme CSS media feature to switch images entirely in HTML:

<picture>
<!-- Light mode image -->
<source srcset="/light.png" media="(prefers-color-scheme: light)" />
<!-- Dark mode image -->
<source srcset="/dark.png" media="(prefers-color-scheme: dark)" />
<!-- Fallback (if prefers-color-scheme isn't supported) -->
<img src="/light.png" alt="Description of image" />
</picture>

2. Switch image based on a CSS selector

If your website allows users to toggle themes manually, for example by adding a .dark class to the <html> tag, you'll need CSS rules to show or hide images based on the theme. Tailwind CSS provides convenient utility classes for this:

<!-- Show image when light mode is selected, hide image when dark mode is selected. -->
<img src="/light.png" class="dark:hidden" loading="lazy" />
<!-- Show image when dark mode is selected, hide image when light mode is selected. -->
<img src="/dark.png" class="hidden dark:block" loading="lazy" />
.hidden {
display: none;
}
/*
* Assumes "dark" is a class added to your <html> or <body> tag
* when dark mode is active.
*/
.dark .dark\:hidden {
display: none;
}
.dark .dark\:block {
display: block;
}

We add the loading="lazy" attribute to each image to enable lazy loading. Without it, the browser may download every image during page load, even if it isn't visible. Lazy loading defers this until the image enters the viewport.