This is the second installation in a 2-part mini-series. In our first post we talked about the basics of styling in React.

To recap: Styling in React is the Wild West with a myriad of approaches, all of them with subtle but important pros and cons. There are actually so many approaches we felt it couldn’t fit in one article, so we broke the subject out into two.

Andrew Hayakawa and Josh Compton both have spent a bunch of time over the last year exploring the various options for styling React projects with Server Side Rendering (SSR) in mind, and have condensed their findings into this mini-series.

The goal of this series is to go over a few of the popular methods for styling in React, and outline their up- and down-sides—we hope it helps you decide which strategy works best for you!

The second half deals solely with a technique called CSS-in-JS—let’s dive in:

CSS in JS

Essentially CSS-in-JS boils down to: you write your styles in JavaScript, similar to the inline styling method we began with, but using third party libraries you can leverage more CSS features like pseudo selectors and elements. And again, similar to the inline method, CSS-in-JS libraries generally offer a solution for managing classnames in the global namespace and allows you to conditionally apply styles based on the state of the component. An added benefit of CSS-in-JS is that unlike style-loaders, you can use CSS-in-JS style configs in React Native applications.

CSS-in-JS has become fairly popular in the React community in recent months—not completely surprising based on the promise of the features listed above…however that popularity hasn’t come without a level of controversy over the erosion of separation of concerns between CSS and JavaScript…we won’t weigh in on that debate here, this article is merely meant to present you with options.

So how can you take part in this CSS-in-JS craze? A lot of the libraries out there have clever ways of styling React components. There are two libraries we liked the most which are Radium and styled-components. We will explore those libraries with features they support and an example.

Radium

Radium is one of the first libraries to employ CSS-in-JS and they bill themselves as “a set of tools to manage inline styles”. The library’s main feature is that it makes creating variations on a set of styles very simple from a developer experience. On top of the features from vanilla inline styling, Radium supports @media queries, automatic vendor prefixing, and animation helpers. Radium also has an API for custom tools and plugins if you’re really ambitious.

The setup for using Radium with a React component looks like this:

import React from 'react';
import Radium from 'radium';
//top-level keys are style variations that can be called by this.props.kind
let styles = {
  base: { color: '#fffff' },
  primary: { background: '#0074D9' },
  warning: { background: '#FF4136' }
};
const ButtonComponent = ((props) => {
  return (
    <button style={[
      styles.base,
      styles[this.props.kind]
    ]}>{this.props.children}</button>
  );
});
const Button = Radium(ButtonComponent);
const ExampleComponent = (props) => {
  return (
    <Button kind="primary">Hey world!</Button>
  )
};

<ExampleComponent /> will output:

<button style="color: #fff;background: #0074D9;">Hey world!</button>

The key piece here is from a consuming standpoint, styles can be tightly coupled to a component’s attributes, thus baking-in implicitly conditional, inlined styles as a feature of React’s component props pattern—you could even argue Radium is just the logical extension of React’s inline style paradigm.

And again, the convenience of styling your components this way doesn’t come without valid criticisms that styling is not a concern of JavaScript and treads down the path of re-inventing the wheel. We’ll let you decide for yourself.

TL;DR

Pros Cons
  • Support for @media queries and pseudo selectors/elements
  • Extendable styles tied to component attributes
  • Automatic vendor prefixing
  • Headless SSR- and React Native-friendly
  • API for plugins/tooling

Styled-Components

Styled-Components is another popular styling library for React and in fact was the most popular last year. The driving philosophy behind styled-components is to keep a component’s styles tightly coupled to the component by setting them in the component itself, and similar to Radium, props passed into the component can be used for implicitly conditional styling.

The main difference between styled-components and Radium is styled-components takes the approach of style-loader and generates a <style /> tag in the head with serialized classnames for each component and the final result of that component’s CSS. There is also an option for server side rendering where the generated CSS can be returned in a string format. This enables more advanced styling such as support for @media queries and pseudo selectors.

This means that when you’re defining your styles, you’re actually creating a normal React component, that has your styles attached to it, similar to how Webpack’s style-loader works with serialized class names. The difference is how the CSS itself is written. styled-components uses Template Strings to allow the developer to write actual CSS, while the style-loader option uses JavaScript objects.

Let’s take a look at the setup:

import React from 'react';
import styled from 'styled-components';
// styled.button is an actual React Component that will return a <button /> element
// with the styles you define with the template string immediately following it.
// Using template strings you can also inject conditional logic directly into your styles
export const Button = styled.button`
  background: white;
  border: 1px solid black;
  ${props => props.default && CSS`
    color: blue;
  `}
  ${props => props.secondary && CSS`
    color: grey;
  `}
`;

From a consuming standpoint, similar to Radium the component’s style variations can then be expressed via component props:

import React from 'react';
import Button from '../button';
const Modal = ({ message }) => {
  return (
    <div className="modal">
      <p>{message}</p>
      <Button default>OK</Button>
      <Button secondary>Cancel</Button>
    </div>
  )
}

The above would output:

<html>
  <head>
    <style type="text/css" data-styled-components="gCCXPn gCCXTs" data-styled-components-is-local="true">
      .gCCXPn {background: white; border: 1px solid black; color: blue;}
      .gCCXTs {background: white; border: 1px solid black; color: grey;}
    </style>
  </head>
  <body>
    <div class="modal">
      <p>{message}</p>
      <button class="gCCXPn">OK</Button>
      <button class="gCCXTs">Cancel</Button>
    </div>
  </body>
</html>

As seen above, CSS is written in ES6 Template Strings instead of JavaScript objects, and injecting conditional styles and variables using tagged template literals. It can be a little confusing to read if you’re not familiar with how styled-components works, so expect a bit of a ramp-up period, but it feels intuitive after using the library for a while.

TL;DR

Pros Cons
  • Styles are written in CSS
  • Styles written in the same file as the component
  • Supports @media queries, pseudo selectors, and animations
  • React Native supported
  • Library uses className prop to apply styles
  • SEO cost from serialized classnames
  • Implementation can look confusing to new devs
  • Muddies the waters between presentation and functionality

Other Alternatives

As we mentioned at the top of this section, this approach to styling your React components has become very popular over the last year or so. There are many other libraries that accomplish similar results for each technique, so many that it would be impossible to go over all of them here—this post attempts to give an overview of a couple prevailing patterns in the paradigm with specific examples using a specific library.

Michele Bertoli wrote an article that summarizes the popular libraries and list them out. If you’re interested in doing a deeper dive, check out his article at CSS-in-JS.

Final Thoughts

Managing the styles for any sufficiently mature project has always been a difficult and complex problem to solve, with wildly different approaches based on highly-specific requirements…and with the advent of component-based libraries like React, that problem certainly has not gotten simpler.

Because of the dynamic nature of the problem, it’s tough to specify “Best Practices” for styling in React—and it seems new and novel approaches emerge every few months, all of them with significant advantages and drawbacks. It can be frustrating dealing with such an equivocal topic, but at the end of the day this is the current nature of the beast—we felt the most help we could give was to lay out some of the more popular options, point out some of the less-obvious pros and cons, and let you, dear reader, decide for yourself.

As with most things in Web development, you’ll likely need to do some experimentation on your own to figure out what best works for you, but then again, that’s why we’re in this industry in the first place, right?

For Andrew’s team, they experimented with more than a few libraries, but found vanilla inlining to be the best approach for their needs since the final result is a PDF, and a PDF doesn’t really care about the tidiness or semantics of the markup.

For Josh’s team, they went with WebPack’s style-loader since the components, while rendered on the server, still eventually feed into regular browsers, and SEO/Accessibility were major considerations.

If you’re interested in diving deeper down this rabbit hole, here are some good articles to get you started:

Further reading