Dark Mode: Conditional Styling using styled-components
Tags: react, webdev, javascript, beginners
Published: 2021-09-27 10:29:54


The styled-components allows you to write actual CSS code to style your components. It also removes the mapping between components and styles – using components as a low-level styling construct could not be easier. Here the official docs of [styled-components](https://styled-components.com/docs)

#Getting Started
For the prerequisite part, you need to have [Node](https://nodejs.org/en/) already installed on your machine.

Next let's create a react app and install styled-components too and then start the application.

```
npx create-react-app react-app
cd react-app
npm install styled-components
npm start
```

#Let's Code
We need to import styled from "styled-components", and we need to create a Container component that will render an div tag. The Container component will act as a wrapper component

```
import styled from "styled-components";

const Container = styled.div`
//CSS to be added here
`
```

To add the button to switch between the dark mode we will using a toggle button created using a check box.

```
<Container>
      <div className="contain">
        <h5>Dark Mode</h5>
        <label class="switch">
        <input type="checkbox" onChange={(e) => setDark(!dark)} />
        <span class="slider round"></span>
        </label>
      </div>
    </Container>
```

CSS for the toggle button:
```
.contain {
    margin: auto;
    position: relative;
    top: 40%;
  }

  h5 {
    margin: 0;
  }
  .switch input {
    opacity: 0;
    width: 0;
    height: 0;
  }

  .slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    -webkit-transition: 0.4s;
    transition: 0.4s;
  }

  .slider:before {
    position: absolute;
    content: "";
    height: 14px;
    width: 14px;
    left: 2px;
    bottom: 1px;
    background-color: white;
    -webkit-transition: 0.4s;
    transition: 0.4s;
  }

  input:checked + .slider {
    background-color: white;
  }

  input:focus + .slider {
    box-shadow: 0 0 1px white;
  }

  input:checked + .slider:before {
    -webkit-transform: translateX(26px);
    -ms-transform: translateX(26px);
    transform: translateX(12px);
    background-color: black;
  }

  .slider.round {
    border-radius: 34px;
  }

  .slider.round:before {
    border-radius: 50%;
  }
```

So this is how the toggle button would look like,
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zxnxxl7z2j2ywe15e42.png)
 
Now let's add the functionality, we will be using useState Hook,

```
  const [dark, setDark] = useState(false);
```

By default the toggle should be off and when toggled the dark value should be true, so let's add onChange property on the input tag,

```
  <input type="checkbox" onChange={(e) => setDark(!dark)} />

```

Next we need to pass the dark value to the Container component so that we can change the background color accordingly

```
<Container dark={dark}>
```

After passing dark value we can change the background conditionally
```
const Container = styled.div`
  background: ${({ dark }) => (dark ? "black" : "white")}; //Conditional styling the background color
  height: 100vh;
  min-height: fit-content;
  .switch {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 16px;
    border-radius: 50%;
    border: 3px solid black;
  }

  h5 {
    margin: 0;
    color: ${({ dark }) => (!dark ? "black" : "white")}; // To change the color of the text opposite to the background color
  }

//Remaining CSS remains the same
```

The entire code:
```
import React, { useState } from "react";
import styled from "styled-components";

const Container = styled.div`
  background: ${({ dark }) => (dark ? "black" : "white")};
  height: 100vh;
  min-height: fit-content;
  .switch {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 16px;
    border-radius: 50%;
    border: 3px solid black;
  }

  .contain {
    margin: auto;
    position: relative;
    top: 40%;
  }

  h5 {
    margin: 0;
    color: ${({ dark }) => (!dark ? "black" : "white")};
  }
  .switch input {
    opacity: 0;
    width: 0;
    height: 0;
  }

  .slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    -webkit-transition: 0.4s;
    transition: 0.4s;
  }

  .slider:before {
    position: absolute;
    content: "";
    height: 14px;
    width: 14px;
    left: 2px;
    bottom: 1px;
    background-color: white;
    -webkit-transition: 0.4s;
    transition: 0.4s;
  }

  input:checked + .slider {
    background-color: white;
  }

  input:focus + .slider {
    box-shadow: 0 0 1px white;
  }

  input:checked + .slider:before {
    -webkit-transform: translateX(26px);
    -ms-transform: translateX(26px);
    transform: translateX(12px);
    background-color: black;
  }

  .slider.round {
    border-radius: 34px;
  }

  .slider.round:before {
    border-radius: 50%;
  }
`;

function App() {
  const [dark, setDark] = useState(false);
  return (
    <Container dark={dark}>
      <div className="contain">
        <h5>Dark Mode</h5>
        <label class="switch">
          <input type="checkbox" onChange={(e) => setDark(!dark)} />
          <span class="slider round"></span>
        </label>
      </div>
    </Container>
  );
}

export default App;

```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ndkanzamdcc0630npu8u.png)
 

This is my first blog on Dev.to.
Hope it was helpful and easy to implement.
Will be looking forward for feedback on this, also check out my Github [thenickrj](https://github.com/thenickrj)