DEV Community

loading...
Cover image for 🦄 How to scope your CSS/SCSS in React JS ⚡️

🦄 How to scope your CSS/SCSS in React JS ⚡️

viclafouch profile image Victor de la Fouchardière Updated on ・3 min read

Hi guys ! 🤗

Next article about React JS! Last week we talked about How to build a complete Modal Component with React Hooks.

This week, let's discover a little trick that will allow you to scope your css/scss/sass in your React JS application.

In order to solve the problem of css encapsulation, there are two main approaches, css-modules and CSS-in-JS.
However, both of them have a very very big problem. The developer experience is not good, by which I mean you often have to write more code than you expect to achieve a simple style.

React SCSS Scoped

Created with meme-studio.io

With react-scoped-css created by @gaoxiaoliangz, you can just write the normal css you know, while having the advantage of css encapsulation!

React Scoped CSS

How does it work ?

Usually, you import your global style file in your React application, or you use a css file by component if like me you like to be rigorous. But the problem with this second approach is that your style is not scoped.

The scoped CSS allows you to targets a specific element and its children without any impact on other component.

Installation:

With create-react-app

Since create-react-app doesn't allow you to change webpack and babel config. So in this scenario, you have to use craco to override webpack config. Luckily you don't have to do it manually, just use a simple craco plugin.

Setup craco following this guide

# npm i craco-plugin-scoped-css --dev
Enter fullscreen mode Exit fullscreen mode

Then, create a craco.config.js in your project root and add this code:

module.exports = {
  plugins: [
    {
      plugin: require('craco-plugin-scoped-css')
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Without create-react-app

You have to add one babel plugin and one webpack loader.

# npm i babel-plugin-react-scoped-css --dev
Enter fullscreen mode Exit fullscreen mode

And in your babel config:

plugins: ["babel-plugin-react-scoped-css"]
Enter fullscreen mode Exit fullscreen mode

Usage:

Just create your component and import your stylesheet. The css filename must be like [name].scoped.css (or .scss/.sass). But you can define your own matching rule (.scoped.css, .local.scss, ...) in the plugin configuration.

React CSS Scoped JSX

Your css (or scss/sass):

React CSS Scoped CSS

Result

React CSS Scoped HTML

As you can see in the html above, component with scoped css file imported has a unique data-v-<hash> attribute.

React CSS Scoped CSS

The css selector also has a corresponding hash like selector[data-v-<hash>]. So all the styles in home.scoped.css are scoped to Home.jsx.

Architecture

One common way to structure projects is to locate CSS, JS, and tests together inside folders grouped by feature or route. So here, let's group our JS and scoped css in a folder for one component!

Alt Text

Example of one of my projects

Voilaaa

You can find the Github Repo here: https://github.com/gaoxiaoliangz/react-scoped-css

Today, I use it on most of my projects and I encourage you to try it!

Cheers 🍻 🍻 🍻

Discussion (5)

pic
Editor guide
Collapse
ghalib profile image
Ghaleb Al-Nakhlani

This is very useful thanks for sharing, you have no idea how I struggled just to find something that works in the same way that you have explained it.
Still, i don`t understand why it's not so simple to scope styles in react.

Collapse
jjbully profile image
Jeffrey • Edited

Am wondering if i can nest scss, which is sthg like below:


.abc {
.efg {
background-color: white;
}
}

Collapse
ghalib profile image
Ghaleb Al-Nakhlani

Please, Where can I find the data-v- same as in your images?

Collapse
leonardoraele profile image
Leonardo Raele

He probably read the final html and css served to the browser. (e.g. the Elements and Styles tabs in chrome Dev Tools)

Collapse
ghalib profile image
Ghaleb Al-Nakhlani

Still, I have one problem there are 3 elements in the CSS (body, h2, h4) but it doesn't scope to the specific component, I wonder why?!