Hi, I'm Simon.

Simon Fletcher is a 24 year old British software engineer currently working with JavaScript at Minbox in San Francisco, CA.

Previously, he was a founder at Y Combinator funded Interstate (acquired by Stripe).

ESTABLISHED 1992
Styling React
April 30th 2016

When it comes to question of how to style React components, the obvious answer is to just do it the same way we have for many years — CSS. Stylesheets are a fundamental building block of the web and there are probably not many (if any at all) websites that you visit which don't load at least one external stylesheet.

So why would you ever consider doing anything else? The idea of building a site without stylesheets sounds crazy at first, but I decided to investigate the idea when I realised the vast majority of styles that I had wrote were almost always directly related to specific React components. I strive for most of my components to be pure and fully encapsulated, so having styles stored and loaded in a completely separate way seemed odd. I wasn't really separating my concerns by using stylesheets separate from my JavaScript; the CSS and JavaScript were still closely coupled. It felt like I was just putting the the same concerns in different files.

After doing a quick bit of searching, I discovered that there are already several alternatives to vanilla stylesheets that exist within the React ecosystem. In this post, I'll explain two different ways of working with styles in a React application. The first option being the most familiar; using .css files but in a slightly more modern way, where as the second option almost entirely drops stylesheets in favour of the style prop.

webpack's css-loader with CSS modules

css-loader is a loader for webpack (used alongside style-loader) which allows you to import a stylesheet as you would any other JavaScript module. It is not specifically designed for use with React but makes a good companion tool since you can store stylesheets directly with components. When importing a .css file, the loader (when module support is enabled) will automatically convert each selector to a unique identifier which can then be used as a class name.

The loader also introduces some additional functionality to CSS, including a composes rule which, as its name suggests, allows you to compose another selector's rules (similar to @extends in SCSS), for example:

.row {
  padding: 5px;
  color: red;
}

.usernameRow {
  composes: row;
  font-weight: 500;
}

is converted to:

module.exports = {
  row: "_23_aKvs-b8bW2Vg3fwHozO",
  usernameRow: "_13LGdX8RMStbBE9w-t0gZ1 _23_aKvs-b8bW2Vg3fwHozO"
}

You can then use these identifiers as values for the className prop (to conditionally combine multiple class names together you can use something like my own class-name module). One of the great things about css-loader is that because it still simply post-processes a stylesheet, you can use it in conjuction with other great webpack loaders such as precss.

css-loader lets you keep the familiarity of CSS but work with it in a more modern, modular way. You can read more about it here: https://github.com/webpack/css-loader.

Radium

Radium is an enhancer for React components. Wrapping a component with the Radium function supercharges the style prop. Radium does this by overloading the render function of the provided component, recursing in to the result of the original render and applying some juice to the style prop of each DOM-based element.

Radium enhances the style prop in a number of ways. The enhancement you'll use the most often is instead of only being able to provide an plain object as a value to the style prop, you can instead pass an array of style objects, which will be flattened together. This alone is a very handy feature for composing styles. Style objects can also include a number of CSS inspired properties (such as :hover) which Radium will automatically apply to your style object when in the correct state.

import React from 'react';
import Radium from 'radium';

const styles = {
  row: {
    padding: 10,
    backgroundColor: 'yellow',
    ':hover': {
      backgroundColor: 'red'
    }
  },
  username: {
    fontWeight: 500
  }
};

const UsernameRow = ({ username }) => (
  <div style={[styles.row, styles.username]}>
    {username}
  </div>
);

export default Radium(UsernameRow);

There are a number of CSS selectors which Radium does not support natively, such as :last-child, but in most cases you can add support for them yourself by simply using a conditional when constructing your array of styles. For example, to add custom styles to the last child in a mapped array of components you can just compare the index to the length of the array:

const names = ['Simon', 'Alexander', 'Mike'];
const length = names.length - 1;

return names.map((name, index) => {
  const style = [
    styles.person.base,
    index === length && styles.person.last
  ];

  return (
    <div key={name} style={style}>
      {name}
    </div>
  );
});

One of the most powerful things about using JavaScript to define your styles is that you can take full advantage of the JavaScript language. Variables, which were only recently added to CSS, are of course available. Composing styles becomes ridiculously easy by using the ES6 spread operator or through building an array of styles. Providing and overriding styles of nested components can easily be achieved — without any need for !important flags.

On the other hand, one of the big negatives of using the style prop rather than a stylesheet is that you lose a lot of great existing tooling - such as the aforementioned precss. The biggest time saver that you lose by using inline styles is most probably the autogeneration of browser vendor prefixes. Luckily, Radium has support for autoprefixing built in. It bundles inline-style-prefixer which takes care of adding only the browser vendor prefixes required to your styles.

If you do decide to use Radium for a project you most likely still won't be completely free from CSS. While you can style all of your React components with Radium if you want to, there will often be times when you need to style components which do not accept style props or DOM elements which are not controlled by React. For those situations, Radium provides a Style component which lets you provide rules scoped to fixed CSS selectors. For example:

<Style
  scopeSelector=".body"
  rules={{
    margin: 0,
    padding: 0,
    inner: {
      padding: 50
    }
  }}
/>

will create the following element:

<style>
  .body {
    margin: 0;
    padding: 0;
  }

  .body .inner {
    padding: 50px;
  }
</style>

Radium has a number of other features including support for media queries and keyframes. You can learn more about Radium at: https://github.com/FormidableLabs/radium.