Getting Started with styled-components 💅
Tags: javascript, react, styledcomponents
Published: 2018-04-04 12:05:52

---
title: Getting Started with styled-components 💅 
published: true
description: a berif starter on using styled-components 
tags: javascript, react, styledcomponents
canonical_url: https://scottspence.com/2018/04/03/styled-components/
---

We're going to style the basic create react app with styled-components to look something like this:

![](https://thepracticaldev.s3.amazonaws.com/i/5dwv10zpqa13wb4pr47l.gif)

But first, preamble✨: I have always struggled with styling sites, it seems to be an aspect of starting web development that is either an afterthought or glossed over. Up until December last year I didn't really like styling anything at all with CSS, it was a chore rather than something I enjoyed doing.

This was until I started using styled-components, when I joined a build to learn project for a [Chingu] voyage ([`grad.then()`] if you're interested) we decided to use a CSS-in-JS package, [Marina] who was on my team was such an inspiration for me watching how components were styled and really gave me the confidence to start using styled-components.

###### me with css before
![](https://media.giphy.com/media/2rj8VysAig8QE/giphy.gif)

I want to share what I have learned so far by going through styling a basic react application.

There's some basic CSS concepts in this post that I was not aware of before starting out with styled-components that I presume are assumed in styling web pages.

Styling the body element of a site is assumed, so for when you are starting out with a blank canvas there are some defaults for all modern web browsers you add to your site, like leaving font size at 16px (or 1rem) or `box-sizing:` `border-box;` there's some packages out there to take care of this for you as well.

## Versions:
**This guide is being used with the following dependency versions.**

react: 16.2.0
react-dom: 16.2.0
react-scripts: 1.1.0
styled-components: 3.1.6

### Install styled-components

Ok lets bootstrap the basic react application you get when using [Create React App] with [`npx`], if you already have Create React App installed globally then you can use the command without `npx`.

```sh
npx create-react-app style-with-styled-components
cd style-with-styled-components/
npm i styled-components
```

Ok, now we have the basic app we can style, thankfully [Dan] has kindly provided the starting styles for us so let's begin my using them with styled-components.

The way the CRA CSS is laid out, assumes that you will have a corresponding CSS file for each component, which can help with maintaining the CSS and lends to the React idea of having all your files separated into their component parts.

We can start with the `App.js` file and it's accompanying `App.css` file. Let's take a look at the `App.js` first:

{% gist https://gist.github.com/anonymous/4c90ae6e909725d5d12e763d784f2e7a %}

In styled-components we'd create components for each of these elements that replace the aforementioned `className`'s. Ok we can start by migrating our styles into components, let's do one component first to get an idea of where we're going with this.

First, import `styled` into the `App.js` module:

```js
import styled from 'styled-components'
```

Now lets look at `<div className="App">`, it's the top level div for this component and is what I like to call the wrapper for the component. So lets give it an imaginative name AppWrapper.

Referring to the App.css there is `text-align: center;` which belongs to this, so:

```js
const AppWrapper = styled.div`
  text-align: center;
`
```

So here we have defined the `AppWrapper` const as a `styled.div` followed by back ticks inside of the back ticks we can write any regular CSS with the exact same CSS syntax you wold in a normal `.css` file.

Now that we have our `AppWrapper` we can replace the top level div on the `App.js` component.

{% gist https://gist.github.com/anonymous/858237f1a474efe6d6d91d662dbff5d2 %}

### styled-components all the things

So let's do that for the remaining four CSS classes, and take a look, I'll define them underneath the `AppWrapper` here:

{% gist https://gist.github.com/anonymous/78967686c6eddf865b955815d5db65fa %}

So first off we've created a variable for the React svg [animation], you'll need to import the `keyframes` helper from styled-components like so:

```js
import styled, { keyframes } from 'styled-components'
```

this can now be used throughout the `App.js` component and we can add an on `hover` selector to any of our styled-components within this module. Here we're going to add it to the `AppLogo` to keep the super sweet rotating React logo.

```js
const AppLogo = styled.img`
  animation: ${rotate360} infinite 120s linear;
  height: 80px;
  &:hover {
    animation: ${rotate360} infinite 1.5s linear;
  }
`
```

Ok, our app shouldn't look any different as we haven't added in our styled-components to the app `render()` method, so let's do that now.

Let's also change the intro text. You can add a wrapper for the `<code>` tags something like:

```js
const CodeWrapper = styled.code`
  font-size: 1.3rem;
`
```

But if you prefer you can nest selectors within the component, like:

```js
const AppIntro = styled.p`
  color: ${props => props.theme.dark};
  font-size: large;
  code {
    font-size: 1.3rem;
  }
`
```

Let's have a look at the `render()` method now…

{% gist https://gist.github.com/anonymous/facab7eccf2b2c8f9080255e3e282741 %}

Now all the classes originally used in `App.js` have been replaced so there's no need for the `import './App.css'` mapping, remove that aaaaand! Still no change!! Which is a good thing because at the moment we're swapping out the `.css` files for styled-components.

Cool, we have now replaced all the css with styled-components, now we can take a look at `injectGlobal`.

Lets take a look at how the `App.js` file should look before we move on:

{% gist https://gist.github.com/anonymous/338575c695c0077049c30b407764b612 %}

### Style the body with injectGlobal

For styling the body of our react app we currently have the `index.css` file that is being imported into the mounting point of our app in the `index.js` file.

To style the body we can use [`injectGlobal`] from styled-components which adds the styles directly to the stylesheet.

To do this you bring in the `injectGolabl` named export from styled-components and add your styles between the back ticks.

The current `index.css` looks like this:

```css
body {
  padding: 0;
  margin: 0;
  font-family: sans-serif;
}
```

Let's add a `theme` folder in the `src` directory and add a `globalStyle.js` file where we can keep all our styles we want to use throughout the app, keeping the styles on one place will make changes simpler.

In `src/theme/globalStyle.js` we'll need to import the `injectGlobal` named export from styled-components and add the `index.css` styles into it:

```js
import { injectGlobal } from 'styled-components'

injectGlobal`
  body {
    padding: 0;
    margin: 0;
    font-family: sans-serif;
  }
`
```

Ok, now we're adding the body style to the stylesheet directly so there is no need for the `index.css` file mapping that is in `index.js` it should look like this now:

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

import App from './App'

import registerServiceWorker from './registerServiceWorker'

ReactDOM.render(<App />, document.getElementById('root'))

registerServiceWorker()
```

We should still have our nice `sans-serif` font going on, but let's add in some nice Roboto for the body and Montserrat for the heading in our `globalStyle.js` module. We can import Google fonts with an `@import` in `injectGlobal` and apply Roboto to the body:

{% gist https://gist.github.com/anonymous/817ad6b6d68fe41600a850a0fdb02ccd %}

Cool now we can add our imported font for or app header, and there's the option if we want all our `<h1>`'s to use the same font we can add that to the injectGlobal in our `globalStyle.js` module.

{% gist https://gist.github.com/anonymous/f7bec1a71b6c7c47300ca71299c39ba4 %}

Then we can adjust the weight on the `AppTitle` component:

```js
const AppTitle = styled.h1`
  font-weight: 900;
`
```

To add the additional styles for fonts like Montserrat and Roboto you can specify them in the `@import url()` you'll notice that Montserrat has `:400,900` after it that is specifying the styles regular (400) and black (900), you can import as many as you like from Google fonts (CDN) but the more you import the longer it will take to load them, if you have a lot of fonts and styles you want in your app then consider adding them to a folder in the project, like:

```js
import Montserrat from './fonts/Montserrat-Regular.ttf'

injectGlobal`@font-face { font-family: Montserrat; src: url(${Montserrat}); }`
```

### Theming

Themes are often used to change the look and feel of a wide range of things at once. For example, you may have a night and day mode like in Twitter. You can create your own themes in styled-components too.

![](https://thepracticaldev.s3.amazonaws.com/i/gwn8czgagns1n1545zgn.png)

### Use the styled-components ThemeProvider

Now say we want to have several components in our app that use a CSS colour property `color: #6e27c5` instead of hard coding it through the app for every component that uses it we can use the styled-components `ThemeProvider`.

For this we will need to import the `ThemeProvider` named export from styled-components, then define a `theme` object where our colour is going to live:

```js
export const theme = {
  primary: '#6e27c5'
}
```

Let's add the newly created `theme` to the `globalStyle` module we created previously.

To make the theme object available throughout the app component we'll wrap our app component in the `ThemeProvider` and import our awesome theme for use in the `ThemeProvider`:

{% gist https://gist.github.com/anonymous/6de5d94a457195ca6939254e38f7094f %}

Now the `theme` properties can be used as props in our styled-components, let's change the `background-color:` in the `AppHeader` component, whilst we're at it let's add a `dark: #222` property to our `theme` object and use that for the `color` property:

```js
const AppHeader = styled.div`
  height: 12rem;
  padding: 1rem;
  color: ${props => props.theme.dark};
  background-color: ${props => props.theme.primary};
`
```

Now we can change our app theme globally

### Ok cool, can you change theme?

This is what I was thinking and it turns out you can, there's a great [Stack Overflow answer] from [Max] on it.

It got me thinking if you can switch between themes rather than define them for different sections like in the SO answer.

I started off by defining two themes (with imaginative names) in the `globalStyle.js` module:

{% gist https://gist.github.com/anonymous/47ef9cb66053eef84e908bc3ab1b740c %}

Now we need a way to switch between the two `theme` objects, let's use a select box for them, let's create a components folder and in there make a `ThemeSelect.js` component, we can worry about refactoring the `App.js` component when I'm not here :

#### ThemeSelect.js

{% gist https://gist.github.com/anonymous/be700e21646e08f3b410fe6e0195ef89 %}

You've probably noticed the `onChange={e => this.props.handleThemeChange(e)` event, we're going to add that method to the `App.js` component along with some state to
manage what theme is selected.

#### App.js

{% gist https://gist.github.com/anonymous/6aee9297c700aff71438e4942bd6ce89 %}

To summarise what we have done with `App.js` here is, add some state to default to theme1 where the two themes are imported as named exports of the `globalStyle.js` module.

Add a method to handle the change of the `ThemeSelect.js` component `handleThemeChange` this is where we can switch between the two `theme` objects.

Let's try it out, we should be able to switch between the two themes we've defined now.

### Extending styled-components

So far our app hasn't got many styled-components that are similar but what if we were to add some buttons…

{% gist https://gist.github.com/spences10/6d9ef0c1cb62e322ef170ad206f63df8 %}

Here I've added a `Button` component to the `globalStyle.js` for us to use in the `App.js` component. For the sake of convenience we're going to add it here, you may find if you have a lot of similar components that you are reusing throughout your app that it may be a good idea to add them all to a `components` folder.

We can import the `Button` as you would any other component and use it in the module, as we're extending it this means we only need to apply the specific styles we want for that button. But first in the `App.js` component we can specify a normal and a primary button:

```html
<Button>Normal Button</Button>
<Button primary>Primary Button</Button>
```

Now to specify another button with the same css as the imported button we can extend it, like in this example we'll make the button take up 40% of the screen width and make the corners more rounded:

```js
const BigButt = Button.extend`
  height: 3rem;
  font-size: 2rem;
  width: 40vw;
  border-radius: 30px;
`
```

Let's also apply the theme for an underline on `create-react-app` and `styled-components` by adding in an `Underline` styled-component:

```js
const Underline = styled.span`
  border-bottom: 4px solid ${props => props.theme.secondary};
`
```

Now we can switch the theme and have it applied to our components using the theme, pretty neat, right?

I have put all of the examples we have gone over here in a working example for you to play around with the theming and styled-components, enjoy.

https://codesandbox.io/s/x26q7l9vyq?from-embed

### Want to know more?

A great resource for getting started with styled-components which really helped me is [Simon Vrachliotis]'s [egghead.io] styled-components [playlist] which is a great foundation for starting out with styled-components 👌 the first lesson is for pro members but the rest are currently available to watch for free.

There's also the [spectrum.chat] community and of course [Stack Overflow].

### Thanks for reading 🙏

If there is anything I have missed, or if you have a better way to do something then please let me know.

Find me on [Twitter] or [Ask Me Anything] on GitHub.

This was originally posted on my [blog].

<!-- Links -->

[chingu]: https://medium.com/chingu
[`grad.then()`]: https://github.com/chingu-voyage3/grad.then/
[marina]: https://twitter.com/mar_biletska
[dan]: https://github.com/gaearon
[packages out there]: https://github.com/sindresorhus/modern-normalize
[box-sizing:]: https://paulirish.com/2012/box-sizing-border-box-ftw/
[create react app]: https://github.com/facebook/create-react-app#create-react-app-
[`npx`]: https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b
[animation]: https://www.styled-components.com/docs/basics#animations
[`injectglobal`]: https://www.styled-components.com/docs/api#injectglobal
[stack overflow answer]: https://stackoverflow.com/a/42899979/1138354
[max]: https://twitter.com/mxstbr
[simon vrachliotis]: https://twitter.com/simonswiss
[egghead.io]: https://egghead.io/
[playlist]: https://egghead.io/playlists/styled-components-4169206d
[spectrum.chat]: https://spectrum.chat/?t=54887141-57a9-4386-807c-ed950c4d5132
[stack overflow]: https://stackoverflow.com/questions/tagged/styled-components
[twitter]: https://twitter.com/ScottDevTweets
[ask me anything]: https://github.com/spences10/ama
[blog]: https://blog.scottspence.me/