How to display alternate content in dark mode using Theme-UI

Eric Howey January 08, 2020

Theme-UI provides a great pattern for implementing dark mode on your Gatsby website. If your site is primarily text, this can be as straightforward as changing a few colors in your theme and off you go.

Most websites are not so minimal and include images, icons, background patterns, etc. If you are lucky, these will all look fine in dark mode but odds are they won’t. For example images that look good with a light background might visually clash against a darker background.

Here is a pattern to conditionally display alternate content such as images in dark mode using the useColorMode hook from theme-ui.

Import the hook from theme-ui

import { useColorMode } from "theme-ui"

Check the current color mode

const [mode] = useColorMode()
const isDark = mode === "dark"

Conditionally display an image based on the color mode

<Img
fluid={
isDark
? data.imageDark.childImageSharp.fluid
: data.imageLight.childImageSharp.fluid
}
alt="The Darkside"
/>

Or conditionally apply a css filter

This will work best with images that are already single toned, e.g. a black and white logo. The code belowis using the sx prop from theme-ui.

<Img
sx={{
filter: isDark ? "invert(1)" : "none",
}}
fluid={data.image.childImageSharp.fluid}
alt="Twofaced imaged"
/>

A full example component switching images in dark mode

/** @jsx jsx */
import { jsx, Styled, useColorMode } from "theme-ui"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
const Darkside = () => {
const data = useStaticQuery(graphql`
query {
imageLight: file(relativePath: { eq: "image-light.png" }) {
childImageSharp {
fluid(maxHeight: 200) {
...GatsbyImageSharpFluid_withWebp
}
}
}
imageDark: file(relativePath: { eq: "image-dark.png" }) {
childImageSharp {
fluid(maxHeight: 200) {
...GatsbyImageSharpFluid_withWebp
}
}
}
}
`)
const [mode] = useColorMode()
const isDark = mode === "dark"
return (
<div>
<Styled.h1>Gatsby Theme Catalyst</Styled.h1>
<Img
fluid={
isDark
? data.imageDark.childImageSharp.fluid
: data.imageLight.childImageSharp.fluid
}
alt="Gatsby"
/>
</div>
)
}
export default Darkside