I’m Luke Smetham, a Developer at Stream with a passion for front-end development and design. There’s a hot debate around standard CSS stylesheets vs. “CSS-in-JS” solutions when building in modern front-end frameworks. In this post, I’m going to weigh up the pros and cons of CSS vs. Styled Components and how it affects the way I write React components.

Over the last few years, CSS-in-JS solutions have become prevalent across the front-end landscape with many offerings such as styled-components, and emotion that provides a way to colocate your components and style definitions.

The power of these libraries lies in the ability to use JavaScript features to enhance reusability & easily create a design system that goes beyond how things appear visually.

For this post, we're going to focus on styled-components specifically and how it has been changing the way people style their React components.

While there are many advantages to using a "CSS-in-JS" solution, naturally, it's quite a polarizing topic amongst front-end developers. I'm going to lay out some of the essential pros and cons of styled-components vs. more "traditional" CSS stylesheets that affect the way I code in React on a day-to-day basis.

Styled Components

Pros

No Globally Scoped Selectors

One of the most significant benefits of using styled-components , in my opinion, is no longer having to worry about your selector names existing in a global scope with cascading overrides.

Consistency

UI libraries are very prevalent in front-end development. They can be great for getting off of the ground quickly, but typically require you to override the CSS selectors written by the author to customize the styles to match your designs.

When using a CSS framework, this can create an unnecessary learning curve, or at the least, you'll find yourself continually tabbing back and forth to find the correct name of the selector you're trying to override in an ocean of CSS.

styled-components make it easy for you to publish a component to NPM and ensure that it is not only super customizable for the user through props and/or extending via styled(Component) but that it always looks & behaves as it did locally due to zero chance of clashing selectors.

Sass Syntax Out-Of-The-Box

In your styled-components definitions, you can use SASS syntax out-of-the-box without having to set up any preprocessors and extra build tools.

Inside your style definitions, you can use the & character to target the current component, and from there, you can target the parent element, children, or sibling elements as well as adding pseudo-selectors.

See the Gist below for some quick examples of you can leverage this syntax to change the styles of a component based on its surrounding elements:

https://gist.github.com/LukeSmetham/2fdb901b5fa5c1e4dc1a880642180d62

Theming

Using Reacts Context API, styled-components provides a ThemeContext that can you can pass a theme object to, making it accessible in any of your components, and by default can be interpolated into your styled definitions.

I often use the theme to store colors, gutter sizes, and utility functions that can manipulate colors, generate shadows & bezier curves, and much more. The world is your oyster here as far as creating a reusable design system and theming makes it really easy to pull all the raw values & colors from a Sketch file and keep every component on the same page.

Tip: I find that for colors, it can be beneficial to use more generic names like text , primary & accent so that the names are not specific to the color value itself. By being more generic, it enables you to create multiple themes (such as a "Dark Mode") with the same key names so that you can switch them out on the fly without having to change any of your style definitions further down the component tree.

Here is a quick Gist with an example of how you can access the theme in styled-components .

https://gist.github.com/LukeSmetham/321835a70731dd0c9cb24ce73dc9aad8

Dynamic Styling

In the same way that you can access your theme, as shown above, you can also access any props passed to the component, opening up powerful opportunities to create reusable, customizable components.

One example of this would be a styled button. Buttons may have multiple sizes, color variations, and other stylistic differences depending on where they appear on a page. However, the markup and any logic would likely be identical between the variations.

Rather than creating multiple class definitions in your undoubtedly behemoth CSS file, you can leverage props to dynamically change the styles in a way that feels natural to anyone comfortable with React.

One way that I use this feature personally is to create a reusable typography component that I can use throughout my app, without ever having to create multiple style definitions.

Tip: See the Gist below for an example of also utilizing the as prop. This prop is a relatively new feature of styled-components that takes the above concept one step further. We also pass a color name from our props to our theme so we can use our color scheme without extending the style definition.

https://gist.github.com/LukeSmetham/fa938f04d2dd834643b49cdc6d490dcc

Cons

Learning Curve

Most, if not all, front-end developers know CSS in some capacity, and styled-components requires you to think a little differently to traditional CSS. Fortunately, the learning curve is relatively short once you are used to styles & components living together.

Additionally, all of styled-components more "advanced" features are optional, and you can use plain old CSS with no issues at all - although this is often an unnecessary hurdle for a team of developers that aren't all on the same page with CSS-in-JS.

Integration With Legacy CSS Can Be Painful

.

Whether you are using something like MaterialUI, or even your existing stylesheets, integrating styled-components alongside them can be confusing to locate & debug styles. CSS files and styled definitions are often nowhere near each other in the codebase (or even largely inaccessible in the case of CSS Frameworks) and give you no means of seeing which CSS definitions relate to which styled-components and how the styles cascade as far as overrides.

Potentially a "Fad"

In comparison to CSS itself, CSS-in-JS is an extremely young concept and naturally is liable to disappear as quickly as it appeared.

Becoming obsolete or going "out of fashion" happens all the time with tech, sometimes sticking around for a while and other times for a relatively short burst of hype.

It can be frustrating for developers - especially if it means refactoring or even totally rewriting your styles down the line when "the next big library" shows up. This fact also accentuates itself - as the old saying goes, "If it ain't broke, don't fix it."

I think it fair to say that CSS and more established frameworks & preprocessors like SASS are far from broken.

Performance

In larger applications & websites, performance and caching of assets is instrumental in maintaining a solid user experience, especially as tech becomes more readily available in areas with slower connections.

styled-components parses all of the style definitions into plain CSS at build time and drops everything them all into tags in the head of your index.html file.

The issue here is that even if you are statically generating your site with something like Gatsby & React, not only is the size of HTML file increasing, but there is no way to chunk the output CSS either.

Moreover, the class names themselves are dynamically generated, too, essentially breaking caching as things can change between builds/renders.

Tip: One way to ease this issue slightly is utilizing code-splitting in your app (check out react-loadable or React Code Splitting ) - because styled-components happens in JS land, code-splitting ensures only the styles & javascript that are necessary for the current page are sent down to the browser, and the rest can be lazily fetched as the user navigates around.

Colocating Can Bloat Your Components

When styling the DOM in any way, not everything works as a reusable component that can apply to multiple elements.

Often styling rules can be specific to one element that is never reused, and for styled-components specifically, there may be a component that is imported and then extended multiple times in different files, creating a lot more code than necessary.

Of course, it makes no sense to abstract the code into its own file in your components folder, so the most obvious place for it is in the same source file as its parent component.