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!
What is Styled-Components?
As per usual, the best way for us to really know what this is let's check out the docs!
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
// 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
// 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>
)
}
How did the implementation change?
- We imported
styled
from thestyled-components
package. - We defined our
ButtonGreen
variable usingstyled.button
. - We described our styles in
ButtonGreen
with CSS syntax! - We use
ButtonGreen
as the component root in ourButton
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
// 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
// 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
// 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
// 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";
`
// 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
// 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
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!
Top comments (10)
This may be a noob question (because I’m a React noob 😅) but why are styled components preferred over importing a CSS style sheet? I feel like that would keep our component files cleaner by not having so much extra code for the styles.
Hey Dylan,
Ultimately I think it comes down to what the application needs from how big it may be, how many developers are contributing, etc. However, if it's less or cleaner code we're worried about there are a number of things to consider down the road with CSS vs Styled Components.
If you're just importing one CSS stylesheet, then off the bat in our JS we technically have less code for our styling because all we have is our
import './style.css'
line and the rest areclassName="some-class"
. Although, there may come a time where we might need to modify styles based on state or props in our react component which can lead us down to potentially adding logic to our components to adjust for this. In larger projects can lead to some messy components.I think what might be a better way to think about styled-components over CSS is that it aims to align itself better with Reacts component-based architecture with scoping styles but also giving you an API that is intended to work well with Reacts component API and patterns, ideally, resulting in a cleaner codebase for your components and your styling.
My first entry in the series may be more helpful for a "Why not use CSS?" question, as I go more into CSS vs CSS in JS for React!
Let's Take a Look at CSS in JS with React in 2019 - CSS & Inline Styling
Phil Tietjen ・ Sep 9 '19 ・ 5 min read
I hope it answers your question and thanks for asking it! :D
Yes that helps immensely! I’ve done one React project so far and it wasn’t huge so as you said depending on the project size I was able to safely use a stylesheet without issue. I can totally see how that can become a problem as projects become more complex though.
For regular CSS: You get rid of global styles.
Say you write a component somewhere that uses the className 'container'. Then you can't use it in any other component style sheet without getting a conflict.
With CSS modules that is not a problem. The selling point against CSS modules is that you get more power. It lets you conditionally apply styles and build styles based on props.
Hey Phil, really good article! Loved the personal touch to it. Can I suggest the next package? 🙂 It's called
goober
github.com/cristianbote/goober. Yeah I know, I'm biased 🎉But my intention is to offer a lightweight solution to a pattern that gives you so much freedom in terms of styling. The web it's large, and one should be careful whenever it builds something, to make sure that whatever you are sending down the wire is small and powerful.
That's goober in a nutshell. A css-in-jss solution in less than 1KB.
Really curious what your thoughts are.
Cheers!
Hey Cristian,
Thanks a lot! I'm glad you enjoyed the article, I try to give the majority of my posts some personal touches.
I will definitely be checking out goober and consider it for the next post! :D
Brilliant job on the 339 github stars and after checking out the docs it looks awesome! (1KB + styled API sounds incredible).
Honestly, this is one of the things I was really hoping for doing this series was to find other solutions that may be newer, less popular, or hidden under the popular go-to solutions.
Thanks for the comment and the recommendation!
The only thing I don't like about styled-components is the huge nested issue when it comes to debugging. With regular CSS/SASS it's easier to pinpoint which class belongs to what component via styles.scss.
Hey Marlon,
I think with the right structure for either approach can minimize debugging issues. I think where styled-components gets an edge is that because it's scoped, Ideally, you would only need to be concerned with it residing in the component's directory.
I typically create a style.js file where I define and export all my styles for my component to import
/ Component
--/ index.js
--/ Component.js
--/ style.js
I hope you enjoyed the read!
Fantastic Read Phil! I love Styled-Components and this article definitely builds on that. This is a great run through for anyone that is interested in Styled-Components and I will be sending this to anyone who asks about it before they dig into the docs.
Hey CodyBrewer,
Thanks a lot! Really glad you enjoyed the read! :D
I also love Styled Components and had a great time writing about the things I like to use in their API.