Eric
Howey.

There is a hidden page you can visit at /you-are-awesome. Didn't want you to miss out on the fun!
Content has not been updated for more than 2 years, proceed with caution.

How to display alternate content in dark mode using Theme UI

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