Color Mode
When you use the ChakraProvider
at the root of your app, you can automatically
use color mode in your apps.
By default, most of Chakra's component are dark mode compatible. To handle color
mode manually in your application, use the useColorMode
or useColorModeValue
hooks.
Tip: Chakra stores the color mode in
localStorage
and uses CSS variables to ensure the color mode is persistent.
useColorMode#
useColorMode
is a React hook that gives you access to the current color mode,
and a function to toggle the color mode.
Calling toggleColorMode
anywhere in your app tree toggles the color mode.
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 signatureconst 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.
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.
Change color mode behavior#
Starting from v1.0, you can now set default color mode or use default OS color mode.
By default, the color mode will be light
.
To support this, extend the default theme with a config
key matching
ColorModeOptions
:
// 1. import `ChakraProvider` component and `extendTheme`import { extendTheme, ChakraProvider } from "@chakra-ui/react"// 2. declare your configuration, these are the defaultsconst config = {useSystemColorMode: false,initialColorMode: "light",}// 3. extend the themeconst customTheme = extendTheme({ config })function App() {return (// 4. pass to `ChakraProvider` as usual<ChakraProvider theme={customTheme}><h1>Example</h1></ChakraProvider>)}
Learn more about customizing your theme.
Add ColorModeScript#
Add the ColorModeScript
to allow Chakra to determine the initial ColorMode
without weird visual glitches.
create-react-app and similar
// index.jsimport ReactDOM from "react-dom"import App from "./App"ReactDOM.render(<>{/* 👇 Here's the script */}<ColorModeScript initialColorMode="light" /><App /></>,document.getElementById("root"),)
With Next.js
// adjust your pages/_document.jsimport { ColorModeScript } from "@chakra-ui/react"export default class Document extends NextDocument {static getInitialProps(ctx) {return NextDocument.getInitialProps(ctx)}render() {return (<Html><Head /><body>{/* 👇 Here's the script */}<ColorModeScript initialColorMode="light" /><Main /><NextScript /></body></Html>)}}
With Gatsby
// gatsby-ssr.jsimport React from "react"import { ColorModeScript } from "@chakra-ui/react"export const onRenderBody = ({ setPreBodyComponents }) => {setPreBodyComponents([<ColorModeScript initialColorMode="light" key="chakra-ui-no-flash" />,])}
Important: If you customize your
initialColorMode
to bedark
, import your custom theme here and referenceinitialColorMode={customTheme.config.initialColorMode}
to keep it in sync.
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:
- Create a reusable wrapper as demonstrated in the examples:
// e.g. src/Chakra.js// a) import `ChakraProvider` component as well as the storageManagersimport {ChakraProvider,cookieStorageManager,localStorageManager,} from "@chakra-ui/react"export function Chakra({ cookies, children }) {// b) Pass `colorModeManager` propconst colorModeManager =typeof cookies === "string"? cookieStorageManager(cookies): localStorageManagerreturn (<ChakraProvider colorModeManager={colorModeManager}>{children}</ChakraProvider>)}// also export a reusable function getServerSidePropsexport function getServerSideProps({ req }) {return {props: {// first time users will not have any cookies and you may not return// undefined here, hence ?? is necessarycookies: req.headers.cookie ?? "",},}}
- Import your wrapper component setting up Chakra:
// e.g pages/index.jsimport { Chakra } from "../src/Chakra"export default function Index({ cookies }) {return (<Chakra cookies={cookies}><h1>Example</h1></Chakra>)}// re-export the reusable `getServerSideProps` functionexport { getServerSideProps } from "./Chakra"
Important: if you're using
Next.js 9.3
or newer, the Next.js team recommends avoidinggetInitialProps
. The following example is for Next 9.2 or older!
// pages/_app.jsimport {ChakraProvider,cookieStorageManager,localStorageManager,} from "@chakra-ui/react"export default function App({ cookies }) {// 2. Pass `colorModeManager` prop - it finds the relevant cookie on its ownreturn (<ChakraProvidercolorModeManager={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 necessarycookies: req.headers.cookie ?? "",}}