Member preview

CSS Modules with React.js

the easy, neutral and hard parts of CSS Modules

I have been using React.js for almost a year. Thanks to it, I have less pain dealing with complex UI interactions and state changes, and React.js significantly boosted my productivity of building new products and features.

However, although React.js gives me the possibility of building UI by single component, what I found out painful is that, CSS still works globally.

Even when I write CSS with great caution, when it comes up with shared styles among several different components, CSS will effect on unexpected places, and mess up with my desired style and layout. And it is always much more difficult to fix, than rewrite.


So, how can we also encapsulate CSS into one component, just like the way we do with React.js?

I did some research on React.js communities and GitHub, I found out CSS Modules may be the right choice.

However, CSS Modules is not the cure for all problems. I discovered that CSS Modules has some issues that it may prevent me from using it. I will talk about the good & bad in the following section.

If you are thinking to use CSS Modules, I hope my experience can give you some ideas on it.


The easy part

  • Encapsulates CSS code, and only enables it to local scope. It’s easy to switch between local and global scope by using :global in CSS file. Alternatively, you can set up the scope on Webpack config as well.
  • Works with PostCSS and other build tools, and it’s easy to configure and use. Together with PostCSS and hundreds of plugins, your code can be powerful.

If you have Webpack/Browserify build environment set up, all you need to do to enable CSS Module is to download packages, add a few lines of code in webpack.config.json, and import CSS files it to your React.js file. Pretty simple and straightforward, right?

The neutral part

  1. No nested CSS. In order for CSS Modules to compile, you should write flat CSS:
.parent .child {
color: red;
}

instead of

.parent {
& .child {
color: red;
}
}

If you prefer writing nested CSS, probably you would spend some time to adjust your coding styles.

The hard part

  1. No support/polyfill for CSS Selectors Level 4 yet. From my research and findings, I have not seen there is a polyfill for CSS Modules to support CSS Selectors Level 4 yet. (maybe it’s time to build a new wheel?)
  2. Hard to share styles among several scopes. Sometimes I need to share some styles in several widgets, something like text colors and paddings. What makes this hard in CSS Modules is that, in order to share these styles on a scope that is bigger than local, but smaller than global, either copy and paste the shared styles into each file, or find a hack to solve the issue. Either way, I feel like it is getting me too much trouble, and I don’t want to spend a lot of my development time on solving this kind of issue.

My choice

At the end, I choose to use PostCSS, instead of CSS Modules.

After spending my time figuring out the pros & cons of CSS Modules, and what is my preference and requirements, I think CSS Modules can be over-engineering. While it does solve global / out-of-scope CSS issue, but it also brings up more complexity and issues. Although it solves global CSS scope issue, it brings up another issues for sharing only small amount of style between 2 or 3 components, and etc.. Well organized & written CSS and HTML markup can always solve CSS scoping issue.

Moreover, what makes me not to use CSS Module is that I want to use new properties & features from CSS Selectors Level 4. Although CSS Modules is great, sadly, it could not be my best choice.


At the end, thanks the awesome open source communities for creating these amazing tools & frameworks! ❤

Read my post for building web widget prototype:

My previous React.js post is here:

I write about my front-end learning experience and tricks.

Follow me for more front-end technology articles!