Editor’s Note: This article was updated with relevant information in July 2021, including styled-components’s current GitHub rating and additional benefits and concerns around using styled-components.
In this article, we will be looking at some of the various benefits of styled-components and why you should consider adopting it as your preferred CSS-in-JS framework.
Styled-components is a CSS-in-JS styling framework that uses tagged template literals in JavaScript and the power of CSS to provide a platform that allows you to write actual CSS to style React components.
Styled components are easy-to-make React components that you write with the styled-components library, where you can style your components with plain CSS inside your JavaScript code. On the official documentation page, you would see the example below:
const Button = styled.a` display: inline-block; border-radius: 3px; padding: 0.5rem 0; margin: 0.5rem 1rem; width: 11rem; background: transparent; color: white; border: 2px solid white; ${props => props.primary && css` background: white; color: palevioletred; `} ` render( <div> <Button href="https://github.com/styled-components/styled-components" target="_blank" rel="noopener" primary> GitHub </Button> <Button as={Link} href="/docs" prefetch> Documentation </Button> </div> )
We can clearly see the button as a JavaScript variable and the styles defined in backticks are plain CSS styles. We also see the nested style property with plain CSS styles. This is how styled-components renders CSS in JavaScript.
I know the subject of CSS-in-JS is heavily debated in the frontend community, especially among React developers, so I’d ask that you keep an open mind.
There are many ways to style a React component. There’s the traditional way of using CSS in external CSS files, which then passes a string as the className
prop to reference them, like so:
render() { return <span className="menu navigation-menu">Menu</span> }
If you have worked with a large web application, you can attest to the fact that the CSS files begin to get bulky, clumsy, and complex. One great solution to this is the introduction of SASS. Although SASS helps, you’ll eventually deal with the same issue due to the sheer number of SCSS files a project can have. Even the abstraction starts to become complex in itself.
You can also inline CSS inside your React components:
const divStyle = { color: 'blue', backgroundImage: 'url(' + imgUrl + ')', }; function HelloWorldComponent() { return <div style={divStyle}>Hello World!</div>; }
This method is highly discouraged by React, as it is neither sustainable nor scalable (more on this later).
Finally, CSS-in-JS is a technique where JavaScript is used to style components. When this JavaScript is parsed, CSS is generated as a style element and attached directly on top of the DOM.
There are a host of CSS-in-JS frameworks out there: styled-components, Emotion, JSS, Radium, Aphrodite, and more. You can see a comparison table here. Styled-components is, however, arguably the most popular. This option looks promising — it’s no wonder there is a very fast, widespread adoption, with over 600k downloads in the past month.
With styled-components, the UI design’s focus shifts from merely styling HTML elements or React components through className
to defining styled components that contain their own styles and are easily reusable across the entire project. So, initially, a sub-heading declaration that looked like this:
<h2 className="subTitle">Gucci Snakes </h2>
With the styles defined like this:
h2.subTitle{ font-size: 2em; color: blue; }
Would become something like this:
import styled from 'styled-components'; const Subtitle = styled.h2` font-size: 2em; color: blue; `; <Subtitle>Gucci Snakes</Subtitle>
The styles become an integral part of the component here, thereby eliminating the key part the CSS classes initially played by removing the mapping between styles and components. This is all built with plain CSS, so there is always a feeling of familiarity you get when working with something you are already used to.
This feeling has been carefully preserved for every user of styled-components, as the syntax is still largely plain CSS.
Ordinarily, inline styling is discouraged by the React team, a concern that is valid because inline styles do not allow the use of pseudos and media queries. Also, inline styles should not be used due to concerns about browser compatibility, camel-casing, and automatically appended scalar quantities.
But with styled-components, we can see a kind of inline styling but without all the aforementioned inline styling baggage. I call it vibranium power. Here is sample code to demonstrate:
const paragraphStyles = { color: red, backgroundColor: black, padding: 2px } <p style={paragraphStyles}> inline styles applied here </p>
Compiled output:
<p style="color: red; background-color: black;"> inline styles applied here </p>
But with styled-components…
import styled from 'styled-components'; const Text = styled.div` color: red, background: black ` <Text>Styled with CSS-in-JS </Text>
Compiled output:
<style> .hash12345tf { background-color: black; color: red; } </style> <p class="hash12345tf">Styled with CSS-in-JS</p>
See how styled-components attached a style tag on top of the DOM, while an inline style just works with the properties of the DOM node instead.
For teams with a React codebase who also use React Native for mobile development, styled-components is one of the best unified solutions out there for you. If consistency across platforms is a priority, then you’ll be glad to know that styled-components can be bundled into React Native.
Using styled-components in React Native, you can just assign alias names to comments, making your JSX code very legible. Also, you can convert any component, even custom components, to a styled component by simply invoking styled()
.
In the frontend tooling world, the team at Vue was (in my opinion) the very first to perfect this concept of scoping styles. There is one very annoying thing about using CSS, and that is the fact that for a non-expert CSS user, it gets incredibly frustrating when you change the style of a particular element or class in your stylesheet and it inversely affects another seemingly unrelated element or behavior in the DOM. This is a great reason to use styled-components, as it is component-based and scoped, like Vue.
styled-components enforces the use of props in the place of classes. This no-class policy has helped them make more developers follow best practices for controlling the behavior of a component.
Initially, you would write:
<h2 className="title primary">Hello World</h2> h2.Subtitle{ font-size: 2em; color: green; &.primary{ color: red; } }
But now, it should be like this:
const Subtitle = styled.h2` font-size: 2em; color: ${props => props.primary ? 'red' : 'green'}; `; <Subtitle primary>Hello World</Subtitle>
Notice how we have managed to keep HTML and CSS manipulations out of the component.
Alternatively, you can always go right back to className
, and the same results will be achieved.
const Subtitle = styled.h2` font-size: 2em; color: green; &.primary{ color: red; } `; <Subtitle className="primary">Hello World</Subtitle>
styled-components supports concurrent server-side rendering with stylesheet rehydration. The basic idea is that every time you render your app on the server, you can create a ServerStyleSheet
and add a provider to your React tree that accepts styles via a context API.
This doesn’t interfere with global styles, such as keyframes or createGlobalStyle
, and it allows you to use styled-components with React DOM’s various SSR APIs.
Owing to the fact that styled-components is indeed made of components, you can unit test them. This is a major CSS breakthrough, and there is already a Jest integration support by the styled-component team.
Jest Styled Components is a set of utilities for testing styled-components with Jest. This package improves the snapshot testing experience and provides a brand new matcher to make expectations on the style rules. It can be installed like this:
npm install --dev jest-styled-components
Here’s an example of a test:
import React from 'react' import styled from 'styled-components' import renderer from 'react-test-renderer' import 'jest-styled-components' const Button = styled.button` color: red; ` test('it works', () => { const tree = renderer.create(<Button />).toJSON() expect(tree).toMatchSnapshot() })
And here’s an example of the resulting snapshot:
exports[`it works 1`] = ` .c0 { color: green; } <button className="c0" /> `
If you followed this article to this point, you must have noticed some nested styles, Sass, and even Polished, a toolset created by the team to further stretch the powers of Sass:
const Link = styled.a` cursor: pointer; text-decoration: none; &:hover { color: blue; text-decoration: underline; } `;
Supporting Sass exposes the core mission of styled-components: to create the perfect CSS-in-JS experience without losing touch with everything we already love about CSS, including reducing the lines of code and other optimization features of Sass.
It’s hard for me to come up with reasons not to use styled-components (especially given the title of the post), but it would be unfair if I did not also point out some (valid) concerns about CSS-in-JS frameworks in this article.
There is a kind of nested lock-in that exists for every user of styled-components, and you should be aware and comfortable with it. You are locked into JavaScript, then into the React library, then finally into styled-components. If any of them goes away, you would have to painfully refactor your codebase.
Some people also indicate the learning curve of styled-components is steep, as well as the unique differences among CSS-in-JS frameworks. I would strongly recommend using and sticking to styled-components.
Styled-components started in 2017, and React developers always ask, “What if it stops being supported?” You have to make sure you are aware of this before using them in production.
People do not like change. This is, in fact, a valid argument as CSS in a separate document is still one of the longest-lasting standards in web development.
Some people feel that the styled-components community is small and they might not get enough support as fast as they need it when they run into difficult bugs, use cases, or errors. This is also valid, but you have to consider the lock-in nature of styled-components.
The truth is if you are not using native CSS inline styles, there is a chance of having some performance overhead with any library you choose to use for styling. However, the little performance overhead you get is the price you pay for the power and flexibility you get from styled-components. The good thing is that styled-components is focused on improving the library’s performance on every new release. It keeps getting better.
There is a massively growing community around styled-components with over 33,000 ⭐️on GitHub, mostly coming from React developers, which is very encouraging and speaks to the prospects of longevity.
It is also very regularly maintained, you can check out the releases page here. If you are a CSS enthusiast, you can check out this State of CSS Survey that is currently all over the internet. Happy coding!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]
7 Replies to "Benefits of using styled-components in React"
Better if you add performance as well in this list
Reasons not to use styled components
Extra page weight as you add lots of extra divs to style your components
More page weight as you need to include a library to replace something you get for free in all browsers
Less code -re-use compared to using proper CSS
Slower than using stylesheets as there is no caching ~ bad for the user
Slower as you have to create inject the styles into the head on each page load
Hard to get a consistent style across a site.
I interview a lot of devs who cannot think of a single reason why styled components have any issues/downside, I don’t mind if people want to use them but no library comes without some downside. I really wish people would focus on the user before using any library, rather than focus on what is comfortable for them as a developer.
Same thing apply for stylesheet in case of adding styles and classes at the top of html in head tag. You can render a component and check!
By the way with the power of browsers these days, those weights you mentioned are almost non performant at all.
Thanks so much for this. Performance and caching are huge. Another developer-related issue that I have is complex functions written directly within the css in style-components. You end up troubleshooting code just to get a style to load in some cases.
“Extra page weight as you add lots of extra divs to style your components”
Not sure where you got that from. It doesn’t add anything to the markup apart from classes.
> Extra page weight as you add lots of extra divs to style your components
Depends on how you create the Styled Components, you can achieve same DOM tree with SCSS or CSS and Styled Components
> More page weight as you need to include a library to replace something you get for free in all browsers
Yeah though you optimize it at Component level. As you are using React, ofcourse there had bee tradeoff in that case as well, you are creating DOM nodes one by one.
> Less code -re-use compared to using proper CSS
Properly done Design System with Styled Components will achieve much higher code reuse
> Slower than using stylesheets as there is no caching ~ bad for the user
If using CSS or SCSS, the CSS is exported to One File with webpack which is more heavier and maybe better cached but whole CSS has been delivered to user even if it is not needed. So we have slower and less performant Initial page load
> Slower as you have to create inject the styles into the head on each page load
Not slower as you are injecting on the component specific styles’ classes and is very small. Combined with Components delivered on need basis, not all the styles get inserted to the HEAD, but the needed ones. Hence not too much is lost.
> Hard to get a consistent style across a site.
Like I said, if done properly, you can have really great experience for site wide experience.
—-
> I really wish people would focus on the user before using any library, rather than focus on what is comfortable for them as a developer.
Of course we are making for user but we don’t wanna spend lot of time debugging fixing CSS quirks because of Cascading effects.
I would prefer very less cascaded levels so that debugging is easy.
As the class names are generated dynamically, there are small, small as 7-10 characters. While CSS or SCSS, need to use ideologies like BEM for less Cascading Conflicts in DOM.
Small class names means saving package size as that class name was not present two times in same bundle (once in CSS and once in HTML)
I really don’t get why this is so popular. Whenever I come across it I’m put off by how ugly it makes the DOM look in developer tools – instead of clean classes like ‘header subheader’ it just adds so much noise to the HTML. Don’t think it’s very good for writing DRY styles either unless I’m missing something. Importing a properly scoped .scss file in every component is so much cleaner IMO.