How to Use SASS and CSS Modules with create-react-app

A short yet detailed guide to styling components with create-react-app

Esau Silva
Bits and Pieces

--

For the most up-to-date version of this article: https://esausilva.com/2020/07/23/how-to-use-sass-and-css-modules-with-create-react-app-cra/

Up until the release of create-react-app v2, if you wanted to include Sass or CSS Modules in your project, you would have to eject from create-react-app, learn Webpack configurations, install Sass loaders and configure it yourself.

Also read:

Photo by Vernon Raineil Cenzon on Unsplash

Not anymore. The team at Facebook released create-react-app v2 and among the many improvements, they gave us the ability to use Sass and CSS Modules right out of the box, and in this tutorial, you will learn how simple it is to include them in your projects using create-react-app.

Let’s create a simple project to demonstrate this.

Tip: Use Bit to build faster with components. It helps your team share and reuse components, and use them to build new applications. Give it a try.

Learn more about reusable CSS components here:

React spinners with Bit: Choose, Play, Install

Getting Sassy with Sass

First create a new project with the latest create-react-app. I will call mine cra-sass

npx create-react-app cra-sass

Aside: If you are unsure of what npx is, or what it does, basically it uses the latest packages from the npm registry, so you don’t need to have create-react-app locally installed.

You will need one new dependency for Sass support. Install node-sass (inside the cra-sass project)

yarn add node-sass

Now rename ./src/App.css to ./src/App.scss.

Once that is done, open ./src/App.js and in line 3 you will find import './App.css'. Change it to import './App.scss'

At this point you can run the app

yarn start

You will see the default template created by create-react-app looking good!

CRA default template

Let’s create another Sass file and name it variables.scss under ./src directory.

Open this newly created Sass file and copy the following:

$primary-color: #282c34;
$secondary-color: #61dafb;

Now open App.scss and modify it as follows (updates in bold)

@import './variables.scss';.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
}
.App-header {
background-color: $primary-color;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: $secondary-color;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

As you can see, we are importing variables.scss and the variables we created for the background color and link color.

If you stopped the app, go ahead and run it again (yarn start). If you didn’t stop the app, head over to your browser and you will see the app still looks the same as before. That’s because we just extracted the colors to a separate file 😄

With that in mind, you now have the full power of Sass within create-react-app without the need to eject and losing support for any future updates to the project.

But wait, there is more! When you build the app, create-react-app will use PostCSS with the Autoprefixer plugin to automatically add the required vendor prefixes.

This works with the browsers list in your package.json. By default, create-react-app ships with the following configuration

"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]

These are the browsers that create-react-app is targeting by default.

If you need support for different browsers (say IE 10) you will need to include the specific browser as follows

"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all",
"ie 10"
]

For a full list of browser queries, head over to the official Browserlist documentation.

One last thing, CSS Grid prefixing is turned off by default. If you need it, you can turn it on by adding /* autoprefixer grid: on */ to the top of your CSS file. However, there are limitations, so familiarize yourself with those.

CSS Modules

The team at Facebook made it really easy to use CSS Modules with create-react-app. You just have to use the following naming convention: [name].module.css or [name].module.scss, where [name] is the name of your stylesheet.

Before proceeding with an example, if you are unsure about CSS Modules, here is the official definition from the repo:

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default.

Basically, same class names do not clash when used in different CSS files. Say you have Button.css and Header.css, then in each of those files you have a class named .bg-color like so

// Button.css
.bg-color{background:red;}
// Header.css
.bg-color{background:blue;}

When React runs, the classes will be actually named something like this .Button_bg-color__18rA{…} and .Header_bg-color__94tO{…}. They follow the following naming convention: [filename]\_[classname]\_\_[hash].

Continuing with the Sass example, open App.scss and add the following

.btn {
width: 200px;
height: 50px;
font-size: 20px;
border-radius: 5px;
margin-top: 20px;
background: rgb(199, 196, 23);
border: none;
&:hover {
background: rgb(236, 233, 36);
}
}

Now open App.js and the bolded code

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.scss';
import Button from './Button';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<button
className="btn"
onClick={() => alert('I am globally styled')}>
I am button 1 - Press Me
</button>
<Button />

</header>
</div>
);
}
}
export default App;

We are basically creating a button and assigning a .btn class to it. We also create a Button component.

Now, let’s actually create the Button component and the related stylesheet file under the ./src directory

touch Button.js Button.module.scss

Notice I am creating a CSS Module here 😉

Open Button.module.scss and add the following

.btn {
width: 200px;
height: 50px;
font-size: 20px;
border-radius: 5px;
margin-top: 20px;
background: rgb(199, 23, 23);
color: white;
border: none;
&:hover {
background: rgb(228, 49, 49);
}
}

To demonstrate, I am using the same class name (.btn) as in App.scss.

Now open Button.js and add the following

import React from 'react';
import { btn } from './Button.module.scss';
const Button = () => {
return (
<>
<button
className={btn}
onClick={() => alert('I am styled with CSS Modules')}
>
I am button 2 - Press Me
</button>
</>
);
};
export default Button;

In bold you will see how we can import the stylesheet to make use of CSS Modules.

You can use destructuring (as I am currently doing) or the dot notation like so

import styles from './Button.module.scss';
...
<button
className={styles.btn}
onClick={() => alert('I am styled with CSS Modules')}
>
I am button 2 - Press Me
</button>
...

It is time to run the app.

yarn start
CSS Modules

Notice the two classes are not clashing. The one globally created in App.scss stayed as .btn and the one created with CSS Modules is now .Button_btn__18rA.

Finally, let’s build the app.

yarn build

Open the generated stylesheet under ./build/static/css/main.[hash].css and you will notice both classes are present, but they don’t clash as they are named differently.

Generated stylesheet

Tip: By decoupling SASS and CSS Modules from your component logic, you can create React components with adaptive styles and dynamic behavior, which can be easily reused (with an open-source toolchain like Bit), independently stored, tested, and documented to drive composable UI design that scales better, and can be maintained better. Learn more here.

Conclusion

I hope you enjoyed this article and thank you for reading. If you have any questions, suggestions or corrections let me know in the comments below. Don’t forget to give this article a share and you can follow me on Twitter!

Thanks for reading! 😃

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--