Let's Take a Look at CSS in JS with React in 2019 - Styled Components
Tags: webdev, css, javascript, react
Published: 2019-11-14 17:07:38


Hey everyone! It's that time again to look at some cool CSS in JS with react. As this series has started rolling I've been trying to think a good way to structure these entries in an interesting and informative way. I've been trying to keep things based on my personal experiences with it; that's not going to change, but I've been conflicted about how deep I should go into the functionality without creating a less polished copy of their whole documentation. Based on some things I've been seeing in the comments in the React-JSS entry I'm going to try to go a little deeper into things.

Thank you, everyone, who has come to check out the series so far and left great comments and reactions. I hope to continue seeing comments for feedback, discussions, and questions! You all rock!

![gif: dante claps with a heart of arrows behind him](https://thepracticaldev.s3.amazonaws.com/i/7crjpaxserhkeohdw571.gif)

## What is Styled-Components?
As per usual, the best way for us to really know what this is let's check out the [docs](https://www.styled-components.com/docs/basics)!

> styled-components is the result of wondering how we could enhance CSS for styling React component systems.

I think this description does a better job selling than explaining so I'm going to try to unpack it so bare with me.

> styled-components allows you to describe your styles with CSS in our React components.

This is probably the closest we are to actual CSS in JS; at least with React specifically, let's take a look at a quick example using our handy green button and inline styling as a baseline to compare.

**Inline Styling**
```jsx
// Button.js
import React from 'react'

const Button = () => {
  const buttonGreen = {
    backgroundColor: "green",
    border: "2px solid white",
    borderRadius: "2rem"
  };

  return(
    <button style={buttonGreen}>
      I think I'm green
    </button>
  )
}
```

**Styled Components**
```jsx
//  Button.js
import React from 'react'
import styled from 'styled-components'

const ButtonGreen = styled.button`
  background-color: green;
  border: 2px solid white;
  border-radius: 2rem;
`

const Button = () => {
  return(
    <ButtonGreen>I think I'm green</ButtonGreen>
  )
}
```

![gif: Dante dancing](https://thepracticaldev.s3.amazonaws.com/i/668y9cpxdnikbpel390i.gif)

#### How did the implementation change?
* We imported `styled` from the `styled-components` package.
* We defined our `ButtonGreen` variable using `styled.button`.
* We described our styles in `ButtonGreen` with CSS syntax!
* We use `ButtonGreen` as the component root in our `Button` component.

Before we go further, let's do a little unpacking with what's happening here.
When we defined our `ButtonGreen` variable we made sure to use pascal case as opposed to our inline counterpart using camel case. This is because with `styled` we are defining a component to be used instead of passing a value into an attribute or prop. The `.button` on line 5 is the HTML element we are choosing as the root element of our `ButtonGreen`, and you can use any HTML element in this chain. The outcome of this generates an HTML element we defined as the root with a hashed className.

Let's also take a look at comparing our trusty Button component from last time with props affecting our styles.

##### Using Props with Inline Styling
```jsx
// Button.js
import React from 'react'

const Button = ({backgroundColour, children}) => {
  const buttonStyles = {
    backgroundColor: backgroundColour,
    border: "2px solid white",
    borderRadius: "2rem"
  };

  return(
    <button style={buttonStyles}>
      {children}
    </button>
  )
}
```

##### Using Props with Styled Components
```jsx
//  Button.js
import React from 'react'
import styled from 'styled-components'

const Button = styled.button`
  background-color: ${props => props.backgroundColour};
  border: 2px solid white;
  border-radius: 2rem;
`

const Button = ({backgroundColour, children}) => {
  return(
    <Button backgroundColour={backgroundColour}>
      {children}
    </Button>
  )
}
```

#### How did the implementation change?
* We passed a prop called `backgroundColour` to our styled component
* We referenced our `backgroundColour` prop value with an arrow function in an interpolated string.

## Phil's Highlights
There's a lot more functionality here to offer; I'm not going to go over everything as that is what the docs are for, but I am going to cover my favorite things. What we've seen so far already had me sold just from how clean everything is because when your components get big, they can get hard to read or retain their context. In my opinion, Styled-Components gives us a great foundation with little effort to make things easier.

### Extending Styles From Components
So far, we've seen controlling styles of a component via props that allow us to create variations of a component with different styling. It's great giving a component the ability to have granular control over a specific CSS property but in my opinion, it does have a fairly messy flaw. As the number the style rules grow for a component, adding more props to specific style rules for a component on top of its props used for functionality really starts to pile up.

##### A possible future for our Button only using props
```jsx
//  Button.js
import React from 'react'
import styled from 'styled-components'

const Button = styled.button`
  background-color: ${({backgroundColour}) => backgroundColour};
  border: ${({borderWidth}) => borderWidth } ${({borderStyle}) => borderStyle} ${({borderColour}) => borderColour};
  border-radius: ${({borderRadius}) => borderRadius}$;
`

const Button = ({
  backgroundColour, 
  borderWidth, 
  borderStyle, 
  borderColour, 
  borderRadius, 
  onClick,
  children
}) => {
  return(
    <Button 
      backgroundColour={backgroundColour}
      borderWidth={borderWidth}
      borderStyle={borderStyle}
      borderColour={borderColour}
      borderRadius={borderRadius}
      onClick={() => onClick()}
    >
      {children}
    </Button>
  )
}
```

I know I know, no one really uses different border styles other than solid. Our very basic button has a lot of props for what it needs to do and will only get bigger and scarier. In my opinion, this is best suited for dynamic styles or special cases.

##### Extending off of Button to make a variation
```jsx
//  SignUpButton.js
import React from 'react'
import styled from 'styled-components'
import Button from '../components/Button'

const SignUpButton = styled(Button)`
  margin: 1rem;
  border-radius: 4rem;
  font-weight: bold;
  color: #fff;
  backgroundColour: "spring green";
`
```
```jsx
// SomePage
import React from 'react'
import SignUpButton from '../components/SignUpButton'

const SomePage = () => (
  <div>
    ...
    <SignUpButton>Sign up now</SignUpButton>
    ...
  </div>
)
```

This is one of my favorite functionalities with the styled API. We're able to extend from the styled `Button` component and create a variation that can add additional styles or overwrite the existing styles we're basing off of; without adding extra props or classes causing the application to have what I like to call a specificity complex. I find this great for splitting a reusable variation into its own file or needing to apply one-off styling when needed without changing the original `Button`.

### Rendering a Styled Component "As"
What if we wanted to render our `Button` with a different root HTML element without creating a different component or modifying the `Button`'s render?

We can do that with the wonderful prop every Styled component gets called `as`

##### Rendering Button as an anchor
```jsx
// SomePage
import React from 'react'
import Button from '../components/Button'

const SomePage = () => (
  <div>
    ...
    <Button as="a" href="#LearnMore">Learn More</Button>
    ...
  </div>
)
```

Minus the potential added prop for `href`, we don't need to do any heavy refactoring of our `Button` component and remains fairly basic to its needs.

## What Do I Personally Like About Styled Components
I've been using Styled Components for a while now, and even though this is early in the series, I think it may be my favorite CSS in JS solution for React. It's one of the reasons I set out to do this series because I needed more of an excuse to see what else is out there; if anything can top it for me.

### Describing CSS with CSS
Object styles abstracted things just enough for it to be cumbersome, so being able to just use regular CSS syntax is great. It's especially great when you're converting CSS rules over to styled-components as for the most part it's copy and paste! There's not really much else to say about it.

### Everything Is Components!
With the styled API, you end up with a lot more contextually named styled-components, which personally, I find much easier to understand what is going on and why in a component. Everything feels that much more declarative like React is intended.

## What Do I Personally Dislike About Styled Components

### Messy React Nodes
If you take a peek into the component's view in the react dev tools, you'll notice your styled-components will have some crazy nesting of context providers. I'm not sure if this really affects too much, maybe some unneeded rendering.

However, not to dismiss this dislike point but in the upcoming version, 5 is fixing this issue and can already be checked out if you install the 5 beta.

## Would I Use Styled Components?
Yes. It's my number 1 choice currently.

## Shout out to Emotion
Some of you may have been screaming at your screens reading this, fingers itching to comment "PHIL, WHAT ABOUT EMOTION?". WELL EMOTION SUCKS!

I'm joking.

Emotion is another CSS in JS solution and offers a little more of a diverse API. Included in that is their emotion/styled API which is conveniently compatible with styled-components API; they're either bitter rivals or best pals. With this, you can pretty much switch between the 2 libraries as you need to with no worry, yet.

I held off mentioning Emotion so I didn't have to use both library names. I will not be making an entry for emotion since I'll just be covering mostly the same stuff.

This marks the end of the entries of libraries I have prior experience with so going forward will be all new territory. If you have any recommendations for what to look at next give me a shout in the comments!

## Time For The Plug

![Friday Night Deploys Podcast by The Devplebs](https://thepracticaldev.s3.amazonaws.com/i/6tbhmfy28hrx9ut71rs1.png)

### We've Started a Podcast!

Keith Brewster and Phil Tietjen are 2 Canadian Web Developers and friends who decided to start what may be best described as a web development-focused and personality-driven podcast show called "Friday Night Deploys". It's a weekly show aimed to release every Friday where we share our experiences and stories about related topics and what we typically get up to in our lives.

### Where To Listen
**Spotify:** https://open.spotify.com/show/7oXdJ5aETg5GBSNC6jZSNq
**Itunes:** https://podcasts.apple.com/ca/podcast/friday-night-deploys/id1485252900
**Google Play Music:** https://play.google.com/music/m/I54hbbplhdmovo2so6cxsctkcaq?t=Friday_Night_Deploys
**PodBean:** https://devplebs.podbean.com/

### Where To Reach Us
**Twitter:** https://twitter.com/DevPlebs (DM's or Mentions welcome)
**Email:** devplebs@gmail.com

We hope you have fun listening and to hear from you!