How to style React with CSS Modules

December 30, 2017

My favorite way to style React components is CSS Modules. It works like vanilla CSS, but with a welcome twist. Let’s say you have a component called HappyDiv, truly the happiest of all divs, with a corresponding JS and CSS file:

HappyDiv.js
import React from 'react'
import styles from './HappyDiv.css'

const HappyDiv = () => <div className={styles.yellow} />

On Line 2, you import styles. On the last line, you set the div’s className to styles.yellow to reference the class straight out of your CSS:

HappyDiv.css
.yellow {
	background: #ffff00;
}

When your application compiles, it will intelligently connect your classnames. So both {styles.yellow} and .yellow will become something like yellow_6h38z. This transformation ensures that other components, although they may be using another {styles.yellow}, will not conflict with HappyDiv’s styling.

Main Benefits

Think of CSS Modules as “plain English CSS that never causes conflicts”. You’ll no longer need to use OOCSS, SMACSS, or BEM since styles don’t collide with each other. And you’ll be able to write regular CSS (not the JS kind) where media queries, keyframe animations, and all CSS properties are supported.

Global Classes

Want to use utility classes or frameworks without importing them into every file? Use :global to create globally-scoped classes.

:global .darkBackground {
	background: #222;
}

The code above would let you use className="darkBackground" anywhere in your application. (Notice that it’s just a string passed to className, not a JavaScript object.) Keep in mind that these classes won’t be transformed by CSS Modules, so there may be style conflicts.

And, although I said “conflicts” in the last line, I don’t believe that using global classes is a bad practice. If you have utility classes or a simple grid system, I recommend globalizing them to avoid duplication.

Structure

I like to create a CSS file for each component, and I stay away from inline styles as much as possible.

components/
├── Button/
│   ├── Button.js
│   ├── Button.css
│   └── index.js
├── Carousel/
│   ├── Carousel.js
│   ├── Carousel.css
│   └── index.js
└── Grid/
    ├── Grid.js
    ├── Grid.css
    └── index.js

Final Word

So far, I’ve been happiest when running a few globally-scoped styles (mainly Silver and a few utility classes) and handing it to CSS Modules to take care of the rest.

Get the articles and announcements that I never post publicly: