DEV Community

Cover image for How to add dark mode in Gatsby + React Project!
HasOne
HasOne

Posted on • Updated on

How to add dark mode in Gatsby + React Project!

for styled component

Adding dark theme become Trend not only on the web but also in desktop, native apps. There are some benefits of adding dark theme to your existing project or next project, dark theme reduces the lights emitted by the screen which helps the reader to read with no pain at night, even day and save battery life...

Get started

prerequisites, install the gatsby project and some packages, follow along:

gatsby new dark-mode

cd dark-mode/
Enter fullscreen mode Exit fullscreen mode

install toggler, button

yarn add react-darkmode-toggler
Enter fullscreen mode Exit fullscreen mode

and also we need styled-components package to use CSS-in-JS

yarn add styled-components
Enter fullscreen mode Exit fullscreen mode

once it's done open up vscode I'll be using for this scenario and and create file named /src/components/Theme/Theme.js there we'll define our theme color for both dark and light:

export const darkTheme = {
  body: "#121212",
  surface: "#1D1D1D",
  font: "#D1D1D1",
}

export const lightTheme = {
  body: "#FFFFFF",
  surface: "#EEF2F5",
  font: "#2A292E",
}
Enter fullscreen mode Exit fullscreen mode

as you see I've created two objects darkTheme for the dark and lightTheme for light (default), you can create a lot of properties like buttonColor, hoverEffect.... but make sure exists in both object darkTheme and lightTheme with CSS color.

Now we need some data to be rendered to screen for that we're gonna use some dummy data. create a folder with a file named Post /src/components/Post/Post.js and there we can add dummy data and style it using styled-components:

import React from "react"
import styled from "styled-components"

const Row = styled.div`
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
`

const Col = styled.div`
  flex: 1 1 30%;
  max-width: 40%;
  margin: 10px;
  height: 150px;
  background: ${({ theme }) => theme.body};
  color: ${({ theme }) => theme.font};
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 10px;
  font-family: sans-serif;
`

export const Post = () => {
  return (
    <Row>
      {[1, 2, 3, 4, 5, 6, 8, 9].map(_ => (
        <Col key={_}>
          <h1>Hello, Gatsby</h1>
          <p>Love to use Gatsb and Learn cool stuff!</p>
          <p>Trying to Add Dark Theme in my Project!</p>
        </Col>
      ))}
    </Row>
  )
}
Enter fullscreen mode Exit fullscreen mode

Rendering nine posts with h1 and two p, to change the color on dark mode and light we have access to theme object inside styled which we created earlier (theme properties).

changing background color, background: ${ }, we need to arrow function it's receiving theme object like background: ${props => props.theme.body}, props.theme.body is we created in Theme.js, make it simpler, destruct it background: ${({ theme }) => theme.body};, go ahead assign it for anything you want, but we haven't yet provide the theme oject to ThemeProvider to make it happen, let do it in /src/pages/index.js, root file:

import React, { useState } from "react"
import { DarkModeToggler } from "react-darkmode-toggler"
import { Post } from "../components/Post/Post"

// Theme Provider
import styled, { ThemeProvider } from "styled-components"
import { lightTheme, darkTheme } from "../components/Theme/Theme"

/**
 * To center Toggler
 */
const Div = styled.div`
  margin: 20px auto;
  display: flex;
  justify-content: center;
`

export default () => {
  const [isDark, setIsDark] = useState("light")

  // Dark mode button toggler
  const darkModeHandler = () => {
    setIsDark(isDark === "light" ? "dark" : "light")
  }

  return (
    <ThemeProvider theme={isDark === "dark" ? darkTheme : lightTheme}>
      <GlobalStyle theme={isDark} />
      <Div>
        <DarkModeToggler
          size="small"
          isDark={isDark}
          onClick={darkModeHandler}
          border="#FFFFFF"
        />
      </Div>
      <Post />
    </ThemeProvider>
  )
}

Enter fullscreen mode Exit fullscreen mode

There you have it! but we also need to change the HTML body color, let create gloablStyle.js in /src/components/Theme/:

import { createGlobalStyle } from "styled-components"
export const GlobalStyle = createGlobalStyle`
  body {
    background-color: ${props =>
      props.theme === 'dark' ? "#121212" : "#FFFFFF"};
  }`
Enter fullscreen mode Exit fullscreen mode

and import the file in the /src/pages/index.js, beneath the <ThemeProvider>, and passing the theme props like:

 <ThemeProvider theme={isDark === "dark" ? darkTheme : lightTheme}>
      <GlobalStyle theme={isDark} />
      /....
    </ThemeProvider>
Enter fullscreen mode Exit fullscreen mode

Alt Text

Thanks for reading my post, Github repo for this project. in the next post, I'll walk you through the CSS/SCSS to add Dark theme, and also for the @material-ui.

Oldest comments (4)

Collapse
 
kevinsolution profile image
Kevin Li

Thanks for posting pretty cute code! 😊

Collapse
 
hasone profile image
HasOne

Really, Thanks for such an awesome response! You're cute too!

Collapse
 
shinesanthosh profile image
Shine Santhosh

Great. Thank you for the post😍😍

Collapse
 
hasone profile image
HasOne

glad to hear it!