DEV Community

Cover image for Become the warrior of the night(Shhh! It's dark mode)
Sobhan Dash
Sobhan Dash

Posted on

Become the warrior of the night(Shhh! It's dark mode)

These days everyone needs a dark mode feature in their app. Why? Well, people love using stuff that doesn't hurt their eyes and can be used discreetly (Yeah, I'm looking at you night owls)

Now a question would be, why not make it dark from the very start?
So the answer would be that there are people who feel it inconvenient to use dark mode, so an accessibility issue arises.

So I was working on building three different apps and decided that I should keep the dark mode toggle too.

Header

Usually, the toggle is placed in the header. Thus, we will create a React component that will hold the button for switching the themes.

Using the React hooks, useState, and useEffect, we make the state and the side effect that will add/remove the class for the dark mode.

function Header() {
  const [ darkMode, setDarkMode ] = React.useState(false)

  React.useEffect(() => {
    const body = document.body
    const toggle = document.querySelector('.toggle-inner')

    // If dark mode is enabled - adds classes to update dark-mode styling.
    // Else, removes and styling is as normal.
    if( darkMode === true ) {
      body.classList.add('dark-mode')
      toggle.classList.add('toggle-active')
    } else {
      body.classList.remove('dark-mode')
      toggle.classList.remove('toggle-active')
    }
  }, [darkMode])

  return (
    <header>
      <div
        id="toggle"
        onClick={() => darkMode === false ? setDarkMode(true) : setDarkMode(false)}
      >
        <div className="toggle-inner"/>
      </div>
    </header>
  )
}
Enter fullscreen mode Exit fullscreen mode

App

Just to create a little content for the page, I have added some text.
We are importing the Header component.

function App() {
  return (
    <main>
      <Header />
      <div id="container">
        <h1>React Dark Mode</h1>
        <p>Uses state to set a class on the body if dark mode is enabled.</p>
        <p>Implementation is done due to a side effect</p>
      </div>
    </main>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
)
Enter fullscreen mode Exit fullscreen mode

CSS

After we are done with the components, we need to style it a bit.
The basic setup is something just removing the margin and padding and the total width and height of an element as box-sizing.

*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
Enter fullscreen mode Exit fullscreen mode

Then we go on and give a basic background, height, and width to our page.

body {
  color: #1a202c;
  transition: color 0.2s ease-in;
}

#app {
  height: 100vh;
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

After that, we need to style the main section and the header.
An interesting addition is the transition property. This provides a smooth change to the background color. And we add position: absolute; in the header so that we can overlap over other elements.

main {
  background-color: #f7fafc;
  height: 100%;
  width: 100%;
  padding: 20px;
  transition: background-color 0.2s ease-in;
}

header {
  position: absolute;
  right: 2rem;
}
Enter fullscreen mode Exit fullscreen mode

Then the container containing the little text that we have written is styled. Nothing too fancy, we just center it to the window and apply a few color variations to the headings and paragraphs

#container {
     display: flex;
     height: 100%;
     width: 100%;
     align-items: center;
     justify-content: center;
     flex-direction: column;
}

#container h1 {
     padding: 0;
     margin: 0 0 10px 0;
}

#container p {
     opacity: 0.8;
}

Enter fullscreen mode Exit fullscreen mode

After we are done with this, 60% is done. All we need to do is implement the styles for the toggle and dark mode variations.

Let's jump into the toggle then:

#toggle {
     width: 50px;
     display: flex;
     padding: 5px;
     background-color: #1a202c;
     border-radius: 1000px;
     cursor: pointer;
     box-shadow: 0px 5px 20px -10px #000;
     transition: background-color 0.2s ease-in;
}

#toggle .toggle-inner {
     width: 20px;
     height: 15px;
     background-color: white;
     border-radius: 1000px;
     transition: margin-left 0.2s ease-in, background-color 0.2s ease-in;
}

#toggle .toggle-active {
     margin-left: 20px;
}
Enter fullscreen mode Exit fullscreen mode

Finally, the dark mode styling is done something like below. We just change the background colors and the text color. That's all

.dark-mode {
     color: white;
}

.dark-mode main {
     background-color: #1a202c;
}

.dark-mode #toggle {
     background-color: white;
}

.dark-mode #toggle .toggle-inner {
     background-color: #1a202c;
}
Enter fullscreen mode Exit fullscreen mode

So that's it. It'll be a big help for your next project, the same as it was for me. I don't have to keep checking different pens for the same thing now xD.

Customize it and have fun!

Discussion (0)