Color Mode

Chakra UI comes with built-in support for managing color mode in your apps.

By default, most of Chakra's components are dark mode compatible. In some scenario, you might need to make your component respond to color mode.

Tip: Chakra stores the color mode in localStorage and appends a className to the body to ensure the color mode is persistent.

Setup#

To get dark mode working correctly, you need to do two things:

  1. Update your theme config to determine how Chakra should manage color mode updates.

  2. Add the ColorModeScript to your application, and set the initial color mode your application should start with to either light, dark or system. It is light by default.

Updating the theme config#

The theme config for color mode has 2 options:

  • initialColorMode: The initial mode you'd like you app to start with
  • useSystemColorMode: If true, your app will change color mode based on the user's system preferences.
// theme.js
// 1. import `extendTheme` function
import { extendTheme } from "@chakra-ui/react"
// 2. Add your color mode config
const config = {
initialColorMode: "light",
useSystemColorMode: false,
}
// 3. extend the theme
const theme = extendTheme({ config })
export default theme

Adding the ColorModeScript#

The color mode script needs to added before the body tag for local storage syncing to work correctly.

When setting the initial color mode, we recommend adding it as a config to your theme and reference that in the ColorModeScript.

To use ColorModeScript on a site with strict Content-Security-Policy, you can use the nonce prop that will be passed to the <script> tag.

For Next.js#

For Next.js, you need to add the ColorModeScript to the _document.js file.

// pages/_document.js
import { ColorModeScript } from "@chakra-ui/react"
import NextDocument, { Html, Head, Main, NextScript } from "next/document"
import theme from "./theme"
export default class Document extends NextDocument {
render() {
return (
<Html lang="en">
<Head />
<body>
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
<Main />
<NextScript />
</body>
</Html>
)
}
}

For Create React App#

For Create React App, you need to add the ColorModeScript to the index.js file.

// index.js
import ReactDOM from "react-dom"
import App from "./App"
import theme from "./theme"
ReactDOM.render(
<>
{/* 👇 Here's the script */}
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
<App />
</>,
document.getElementById("root"),
)

For Gatsby#

For Gatsby.js, you need to add the ColorModeScript to the gatsby-ssr.js file.

// gatsby-ssr.js
import React from "react"
import theme from "../theme"
import { ColorModeScript } from "@chakra-ui/react"
export const onRenderBody = ({ setPreBodyComponents }) => {
setPreBodyComponents([
<ColorModeScript
initialColorMode={theme.config.initialColorMode}
key="chakra-ui-no-flash"
/>,
])
}

Changing Color Mode#

To manage color mode in your application, chakra exposes the useColorMode or useColorModeValue hooks.

useColorMode#

useColorMode is a React hook that gives you access to the current color mode, and a function to toggle the color mode.

Editable Example

Calling toggleColorMode anywhere in your app tree toggles the color mode from light or dark and vice versa.

useColorModeValue#

useColorModeValue is a React hook used to change any value or style based on the color mode. It takes 2 arguments: the value in light mode, and the value in dark mode.

// Here's the signature
const value = useColorModeValue(lightModeValue, darkModeValue)

Here's an example that changes the background-color and color using the useColorModeValue hook.

Click the Toggle Mode button to see it in action.

This box's style will change based on the color mode.
Editable Example

Forcing a specific mode#

In some occasions, you might want Chakra components to look the same in both light and dark modes. To achieve this, wrap the component in a LightMode or DarkMode component. Doing this will override the global colorMode.

Click the "Toggle Mode" button to see it in action.

Editable Example

Add colorModeManager (Optional)#

For server-side rendered sites, e.g. in Next.js, you may want to know the color preference of a user upfront so you can avoid rendering the initial color mode and then changing it during hydration (so-called flashing).

If you don't use SSR or don't care about this, you don't need to pass anything. Chakra will use localStorageManager by default.

Here's how to do this in Next.js 9.3 or newer:

  1. Create a reusable wrapper as demonstrated in the examples:
// e.g. src/Chakra.js
// a) import `ChakraProvider` component as well as the storageManagers
import {
ChakraProvider,
cookieStorageManager,
localStorageManager,
} from "@chakra-ui/react"
export function Chakra({ cookies, children }) {
// b) Pass `colorModeManager` prop
const colorModeManager =
typeof cookies === "string"
? cookieStorageManager(cookies)
: localStorageManager
return (
<ChakraProvider colorModeManager={colorModeManager}>
{children}
</ChakraProvider>
)
}
// also export a reusable function getServerSideProps
export function getServerSideProps({ req }) {
return {
props: {
// first time users will not have any cookies and you may not return
// undefined here, hence ?? is necessary
cookies: req.headers.cookie ?? "",
},
}
}
  1. Import your wrapper component setting up Chakra:
// e.g pages/index.js
import { Chakra } from "../src/Chakra"
export default function Index({ cookies }) {
return (
<Chakra cookies={cookies}>
<h1>Example</h1>
</Chakra>
)
}
// re-export the reusable `getServerSideProps` function
export { getServerSideProps } from "./Chakra"

Important: if you're using Next.js 9.3 or newer, the Next.js team recommends avoiding getInitialProps. The following example is for Next 9.2 or older!

// pages/_app.js
import {
ChakraProvider,
cookieStorageManager,
localStorageManager,
} from "@chakra-ui/react"
export default function App({ cookies }) {
// 2. Pass `colorModeManager` prop - it finds the relevant cookie on its own
return (
<ChakraProvider
colorModeManager={
typeof cookies === "string"
? cookieStorageManager(cookies)
: localStorageManager
}
>
<h1>Example</h1>
</ChakraProvider>
)
}
App.getInitialProps = ({ req }) => {
return {
// first time users will not have any cookies and you may not return
// undefined here, hence ?? is necessary
cookies: req.headers.cookie ?? "",
}
}

Color Mode Flash Issue#

In some cases, when you switch to dark mode and refresh the page, you might experience a quick flash of white mode before it switches correctly.

This is a known issue and we're looking to fix it. If you have some ideas, feel free to share with us on Discord or Github.