Understand the React styling paradigms

One of the first choices you need to make when starting a new project using React is what library to use for styling your components.

There are a ton of options to choose from and the community hasn't yet reached a consensus of what is the best way to style components. So where do you start?

Instead of going over each library in detail, I find it helps to first understand the high level picture  - what are the general approaches related to styling and only from there start to see where each library fits.

Three main styling paradigms

There are 3 main styling paradigms in the React world right now, and the CSS in JS one can further be split into three approaches, since it’s such a broad area:

CSS in JS:

Let’s break them down!

Vanilla CSS

This is the way we've all worked with CSS until now - just plain CSS/LESS/SASS files that we included inside index.html.
The best practice is to have a CSS file for each component, inside the component folder.
You can choose to bundle the CSS files either manually or through Webpack.

How you would use it

  • each component gets its own CSS file
  • manually refer to the CSS classes via className

Pros

  • works out of the box
  • great to get started quickly and for beginners
  • default option for create-react-app

Cons

  • CSS is global

Common "power-ups"

  • BEM naming convention
  • LESS / SASS

CSS Modules

This option builds on top of "Vanilla CSS", so each component has its own CSS file, however the difference here is that the file is locally scoped. So you can give your classes very generic names, like “button” or “box” and they will not clash with anything else in other files.

How you would use it

  • each component gets its own CSS file that is locally scoped; use :global to explicitly define global styles
  • enable the "CSS Modules" flag on the Webpack css-loader

Pros

  • private CSS - you no longer need to worry about CSS class name clashes
  • naming best practices are enforced by default (as opposed to BEM where you are counting on a convention); you will see classes like .hsbrys a lot since they are given random names

Cons

  • you must use separate CSS file, you cannot colocate your styles with the component code

Read more

CSS in JS

Using CSS styles inside the JS code was first introduced by Christopher Chedeaux in 2014 (see the presentation and slides ).

His presentation highlighted the main problems CSS has when used at scale, with a big codebase and a big team of developers.

1. Global namespace

  • CSS is global by default; This is something we know is a bad practice in other languages yet we don’t bother with in the CSS world

2. Dependencies

  • It’s really hard to tell where a class is used, what other styles apply to a given component and if it’s safe to delete a piece of CSS, because dependencies are not explicit;

3. Dead code elimination

  • It’s also really hard to tell which code is not used, so you cannot just remove it for the production build

4. Minification

  • We already minify JavaScript variable names; Why wouldn’t we minify CSS class names?

5. Sharing constants

  • How do you share constants between your JavaScript and CSS code?

6. Non-deterministic resolution

  • CSS is executed in the order the classes are declared, which is linked to the order the files are included; This means that unless you explicitly define the order in which your CSS files are included, you have no guarantee of which class / override will be loaded first

7. Isolation

  • How do you make sure that the styles that you intended are not overridden from the outside? If you’re working on a small plugin that can be embedded in external websites or such, you would want to make sure your base styles are not overridden by the outside CSS; however that’s not the case - CSS cascades, allowing external parties to override anything.

His presentation sparked the community to create a number of libraries, approaching the CSS in JS idea from different angles.
This is why I found it useful to group the CSS in JS approaches in 3 different categories.

CSS in JS: Inline styles

Assign styles to a variable and apply them directly:

const buttonStyle = { backgroundColor: ‘green’ };
return <button style={buttonStyle}></button>

This is a quick way to apply styles and works out of the box as described in the official React docs.

How you would use it

  • attach style to the style attribute of an element

Pros

  • supported natively, works out of the box

Cons

  • very common CSS features no longer work natively - pseudoselectors, media queries

Noteworthy libraries

Read more

CSS in JS: Generated class names

How you would use it

  • attach styles to the className attribute of an element
// Example using Aphrodite
import { StyleSheet, css } from 'aphrodite';

const styles = StyleSheet.create({
  button: { backgroundColor: 'green' }
});

const ButtonComponent = () => (
  <button className={css(styles.button)}>Hello!</button>
);

Pros

  • solves many of the 7 issues CSS in JS aims to solve, with the benefit that you can use all CSS features (unlinke inline styles - media quries, pseudoselectors etc.)

Noteworthy libraries

Read more

CSS in JS: Styled components

If you think about it, in all approaches described above, you need to define a variable or a class describing the styles and then you need to map an element to the given object/class. But actually you always have a one-to-one relationship, so why declare the class name at all?
With styled components you encapsulate styles by creating display components.

import styled fromm 'styled-components';
const GreenButton = styled.button`
  background-color: green;
`;
const helloComponent = () => (
  <GreenButton>Hello!</GreenButton>
);

How you would use it

  • define styles as part of the component definition
  • using class names is no longer needed at all

Noteworthy libraries

Read more

Wrap up

Hope this gave you a better overview of the React styling world. Is there anything you want to learn more about that I didn't cover?