Create a theme with styled-components easily in 3 steps. 💅
Tags: css, javascript, react, tutorial
Published: 2020-11-13 13:44:47

What if you're working on a React based project and suddenly your design team says:

> "Yo, we need to completely change the entire theme of the app due to _blah_ and _blah_ reasons..."

Maybe you're not convinced with their reasons or maybe you just need to do this for fun. Whatever the reason, it's quite annoying if you’re just using plain old CSS (even with [variables](https://dev.to/dailydotdev/css-variables-but-with-a-dash-of-javascript-244j)) to apply the global or per-element styles.

What comes to the rescue is some method by which you can easily change the entire color, font, gradient, etc. values in one go, a place where all of these are defined in a central place so you don’t have to change things here and there.

What I'm talking about is creating your own theme with _styled-components_.

---

# A quick note on styled-components 📝

> **[styled-components](https://styled-components.com/)** is a library that allows you to write actual CSS code to style your components inside a JS file. This follows the [CSS-in-JS concept](https://medium.com/dailyjs/what-is-actually-css-in-js-f2f529a2757) which allows developers to style using tagged [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) giving extensive flexibility and more control.

All in all, a great merger of CSS and JS! Here are some of its features:

- **Automatic critical CSS**: it keeps track of which components are rendered and injects their styles and nothing else, automatically.

- **No class name bugs**: there are no duplication, overlap, or misspellings.

- **Easier deletion of CSS**: if the component is unused and gets deleted, all its styles get deleted with it.

- **Simple dynamic styling**: styling of a component based on its props without having to manually manage dozens of classes.

# What we will be styling? 💅

This:

![styled components button theming](https://dev-to-uploads.s3.amazonaws.com/i/a8ivog3vego5fnj1zndz.gif)

We will be theming out two buttons using styled-components. Notice that we have:

- Different default and hover _colors_.
- Different font _styles_.

Not this:

![Hair styling GIF](https://media.giphy.com/media/W3Hi0XQoCmfqQf868O/giphy.gif)

# Create global styles! 😍

After you're done [installing the library](https://styled-components.com/docs/basics#installation), head over to your _index.js_ file. Here, all the theme data will go such as the colors, fonts, etc.

#### STEP 1️⃣ : Create a `theme` object

This will house all the theme objects we need. Currently, we are only changing the `colors` and `fonts`.

```js
const theme = {
  colors: {
    primary: "#6200ee",
    primaryVariant: "#ede6ff",
    secondary: "#008073",
    secondaryVariant: "#deffff"
  },
  fonts: {
    material: "Roboto",
    default: "Montserrat"
  }
};
```

As we can see, there are four color options, one for each variant; primary and secondary. As for the font, we also need to include them in our _index.html_ file via the `<link>` method as follows:

```html
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />

<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;700&display=swap" rel="stylesheet" />
```


#### STEP 2️⃣ : Use the `ThemeProvider` component

Next, import the [`ThemeProvider`](https://styled-components.com/docs/api#themeprovider) helper component from `styled-components`. This is used to inject the theme into all styled-components in the component tree, via the [Context API](https://reactjs.org/docs/context.html).

We need to wrap our top-level component i.e. `<App />` with this. But for it to actually recognize the `theme` object we wrote above, we need it to pass it on as:

```jsx
<ThemeProvider theme={theme}>
    <React.StrictMode>
        <App />
    </React.StrictMode>
  </ThemeProvider>
```
Hence, now the render methods becomes:

```jsx
ReactDOM.render(
  <ThemeProvider theme={theme}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ThemeProvider>,
  rootElement
);
```

#### STEP 3️⃣ : Create the buttons and add the theme!

Before we hop into the buttons, did you see that the body color of the demo is not white but instead off-white? Well, here, the global style of the app was triggered.

Using the [`createGlobalStyle`](https://styled-components.com/docs/api#createglobalstyle) helper function, we can change or reset the base styles of the entire application.

For this to happen, we need to add the `<Global />` component just before the `<App />` starts inside the `App()` function.

Now we can add global styles by defining the usual styled-component:

```jsx
const Global = createGlobalStyle`
  body {
    width: 50%;
    padding: 10px;
    background: #fffaeb;
  }
`;
```

Okay, let's move to those two buttons. We can create two components; `<PrimaryButton />` and `<DefaultButton />`

The usual styles (without colors and fonts) for the buttons are as follows:

```css
  .
  .
  .
  width: 50%;
  height: 50px;
  cursor: pointer;
  transition: all 200ms ease;
  text-decoration: none;
  outline: none;
  border: none;
  border-radius: 10px;
  float: left;
  .
  .
  .
```

To get the value from the `theme` which is passed via the `ThemeProvider` component, we will use our good old friend in React, i.e. [props](https://reactjs.org/docs/components-and-props.html)! 

Start with the template literal syntax to pass on the `props` parameter to our arrow function, this can now get the global theme object via `props.theme`. Now we got the `theme` object, so we can assign the values as follows:

```css
background: ${(props) => props.theme.colors.primary};
color: ${(props) => props.theme.colors.primaryVariant}; 
```

We applied the colors, now what about the hover effect? styled-components makes it really easy to add [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) whether it's `:hover` or `:active`. Just invert the values of the `background` and `color` inside the `:hover` object:

```css
:hover {
    background: ${(props) => props.theme.colors.primaryVariant};
    color: ${(props) => props.theme.colors.primary};
  }
```

The same method is applied to other objects inside our `theme` such as for the different fonts:

```css
  .
  .
  .
  font-family: '${(props) => props.theme.fonts.material}';
  font-weight: 500;
  .
  .
```

And that's pretty much it! You have used a theme in styled-components. Of course, this is just the beginning, you can bring in the entire library of design assets and tokens with your theme to make it even more dynamic.

---

# More resources 🤩

Go ahead with theming when you read from these resources:

- [Theming docs by styled-components](https://styled-components.com/docs/advanced#theming)
- [How to use Themes in styled-components by @aromanarguello](https://dev.to/aromanarguello/how-to-use-themes-in-styled-components-49h)
- [styled-theming repo by styled-components](https://github.com/styled-components/styled-theming)

---

_Thanks for reading, I appreciate it! Have a good day. (✿◕‿◕✿)_

---
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="en" dir="ltr">When the going gets tough, the tough get going. 💪<br><br>Image source: <a href="https://t.co/f3Mij3xXQs">https://t.co/f3Mij3xXQs</a><a href="https://twitter.com/hashtag/DevHumour?src=hash&amp;ref_src=twsrc%5Etfw">#DevHumour</a> <a href="https://twitter.com/hashtag/CodingMemes?src=hash&amp;ref_src=twsrc%5Etfw">#CodingMemes</a> <a href="https://twitter.com/hashtag/Developer?src=hash&amp;ref_src=twsrc%5Etfw">#Developer</a> <a href="https://t.co/bouXm7eVlx">pic.twitter.com/bouXm7eVlx</a></p>&mdash; Microsoft Developer UK (@msdevUK) <a href="https://twitter.com/msdevUK/status/1324630107240222720?ref_src=twsrc%5Etfw">November 6, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
---

#### [📫 Subscribe to my weekly developer newsletter 📫](https://mailchi.mp/f59beeac6b9b/devupdates)

##### PS: From this year, I've decided to write here on DEV Community. Previously, I wrote on Medium. If anyone wants to take a look at my articles, [here](https://medium.com/@vaibhavkhulbe)'s my Medium profile.