Theming with styled-components ThemeProvider
Tags: react, styledcomponents
Published: 2021-04-10 15:07:23

---
title: Theming with styled-components ThemeProvider
published: true
date: 2021-04-10 15:00:00 UTC
tags: react, styledcomponents
canonical_url: https://www.rossanodan.me/theming-with-styled-components/
---

If you are here probably you already know what `styled-components` is so let’s skip the small talk.

Prerequisites for this post is having a React-based application. If you have it, proceed reading. If you don’t, [take a look at this](https://github.com/facebook/create-react-app) before proceeding.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#installing-styled-components)Installing styled-components

Run the following command to install the npm package (or use `yarn`, as you wish)

```
npm install styled-components
or
yarn add styled-components
```

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#creating-themejs-component-with-themeprovider)Creating Theme.js component with ThemeProvider

Now, create `Theme.js` file. This file will be your application’s theme entry point.

```
import { ThemeProvider } from 'styled-components';

const theme = {};

const Theme = ({ children }) => {
  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};

export default Theme;
```

The `theme` object is where you’re going to define your theme variables like colours, font sizes and so on. As far as I know there isn’t a perfect way to define this object so it’s up to you to find _your perfect_ way to do so.

I’ll give you an example below

```
const theme = {
  colour: {
    primary: '#3D315B',
    secondary: '#444B6E',
    background: '#708B75',
    link: '#9AB87A',
  },
  font: {
    size: {
      extraSmall: '14px',
      small: '16px',
      medium: '18px',
      large: '20px',
      extraLarge: '24px',
    },
    family: 'sans-serif',
  },
  breakpoint: {
    mobile: '375px',
    tablet: '600px',
    laptop: '1200px',
    desktop: '1600px',
  },
};
```

So now your `Theme.js` file should be something like this

```
import { ThemeProvider } from 'styled-components';

const theme = {
  colour: {
    primary: '#3D315B',
    secondary: '#444B6E',
    background: '#708B75',
    link: '#9AB87A',
  },
  font: {
    size: {
      extraSmall: '14px',
      small: '16px',
      medium: '18px',
      large: '20px',
      extraLarge: '24px',
    },
    family: 'sans-serif',
  },
  breakpoint: {
    mobile: '375px',
    tablet: '600px',
    laptop: '1200px',
    desktop: '1600px',
  },
};

const Theme = ({ children }) => {
  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};

export default Theme;
```

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#using-themejs)Using Theme.js

Now that your `Theme.js` component is ready, you can wrap your React app with it. Go to your React entry point and wrap everything with `<Theme>...</Theme>`

```
import React from 'react';
import ReactDOM from 'react-dom';

import Theme from './Theme';

ReactDOM.render(
  <Theme>
    <header></header>
    <main>
      <p>Hello, there!</p>
    </main>
    <footer></footer>
  </Theme>,
  document.getElementById('root')
);
```

Great, now you need a `styled component` to see `ThemeProvider` in action.

```
// import styled-components
import styled, { css } from 'styled-components';

// create Text component
const Text = styled.p`
  ${({ theme }) => css`
    color: ${theme.colour.primary};
    font-family: ${theme.font.family};
    font-size: ${theme.font.size.medium};
  `}
`;

// use Text component created above
<main>
  <Text>Hello, there!</Text>
</main>;
```

As you can see, wrapping the whole application with `ThemeProvider`, the styled components receive `theme` in the `props`.

And this is the result

[![Result](https://www.rossanodan.me/static/485c12f634c50460ffe9a27bb6d3cac5/fcda8/Result.png "Result")](https://www.rossanodan.me/static/485c12f634c50460ffe9a27bb6d3cac5/29beb/Result.png)

Powerful, eh? **But there’s more**. You can work with media queries in the same way.

Imagine that you want to change the style of `Text` component only for mobile devices.

```
const Text = styled.p`
  ${({ theme }) => css`
    color: ${theme.colour.primary};
    font-family: ${theme.font.family};
    font-size: ${theme.font.size.medium};

    // media query
    @media (max-width: ${theme.breakpoint.mobile}) {
      font-size: ${theme.font.size.small};
      background-color: ${theme.colour.background};
    }
  `}
`;
```

And this is how it should look like for `376px` and `375px` respectively.

[![Text for resolution 376px](https://www.rossanodan.me/static/922a6be44f3b389b3128c04fdf0df0b1/fcda8/MediaQuery376px.png "Text for resolution 376px")](https://www.rossanodan.me/static/922a6be44f3b389b3128c04fdf0df0b1/769f8/MediaQuery376px.png)

[![Text for resolution 375px](https://www.rossanodan.me/static/c679f0ddcae49e00d6efac1f4b5699c5/fcda8/MediaQuery375px.png "Text for resolution 375px")](https://www.rossanodan.me/static/c679f0ddcae49e00d6efac1f4b5699c5/769f8/MediaQuery375px.png)

You made it! You now have a basic theming setup for your React app!

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#whats-next)What’s next?

From this point it would make sense improving this theming setup to allow multiple themes like, for example, dark and light theme.