Skip to content
loading...

PostCSS with CSS Modules and React

Dave Irvine on June 14, 2018

Updates 02/10/18 - Looks like Create React App now adds support for CSS Modules Quick Intro CSS Modules are meant as a way... [Read Full]
markdown guide
 

I really love that I found your article which still seems to work (these things are so damn timely haha). I do find the ident thingy super duper frustrating. I'm utilizing css modules composes and for just two classes btn btn-primary it's resulting in src-components-___base__button___3KDTY src-components-___base__btn___1Fsux which is ridonkulous to read.

Also, I don't know that I understand the whole styleName thing. Is that required? I seem to be fine leaving className.

Anyway, thanks for the step by step!

 

See my other comments for more on styleName, but you don't have to use it, it can exist alongside className or be ignored entirely. :)

 
 

Hi,

This is a great tutorial, but I think you have an issue in your code. You see, you can't use postcss-import with CSS modules without creating a whole bunch of duplicates. Every file in which you import your colors.css gets inlined which creates a bunch of duplicate :root statements in your final CSS.

You can see more in this issue: github.com/postcss/postcss-import/...

 

Hi, thanks for the feedback! Yes it looks like duplicate roots are definitely an issue, unfortunately as far as I can tell there is no current way around it?

 

There isn't an official or suggested way around it, as far as I know, while I was dealing with this problem. But there are some workarounds. I'm using postcss-preset-env and there's an importFrom option. There you can load a file with variables which are going to be provided for each file, so there's no need to import them manually.

Downside is that you can only import .css, .js or .json. Which is unfortunate if you're using something like SASS, LESS or simply different syntax like SugarSS. So you have to keep variables in different file type than all the others. When it comes to mixins, they don't get injected so I import them per file.

Another possibility is to use one of the deduplication plugins provided.

Last one I can think of is just use postcss-simple-vars, instead of :root and native CSS variables.

Although I was using variables like this plugin supports, I like to use native CSS variables when they're supported, even though I like plugin syntax better.

Hope this helps as bit.

 

Hi,

Thanks for the great tutorial.
I have the configurations as explained in the tutorial but still css files are throwing error:

Module build failed (from ../node_modules/postcss-loader/src/index.js):
Error: Cannot find module 'react-css-modules'

webpack.config.js:

{
test: /.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]',
},
sourceMap: true,
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
},
],
},

postcss.config.js:

plugins: [
require('postcss-inline-svg'),
require('postcss-import'),
require('postcss-pxtorem')({...}),
require('postcss-mixins')({...}),
require('react-css-modules'),
require('postcss-color-gray'),
require('postcss-preset-env')({
browserslist: [...],
stage: 3,
features: {
'custom-properties': {
preserve: false,
},
'nesting-rules': true,
'color-mod-function': { unresolved: 'warn' },
},
}),
require('postcss-extend'),
],

.bablerc:

"plugins": ["@babel/plugin-proposal-object-rest-spread", "lodash",
["react-css-modules", {
"webpackHotModuleReloading": true,
"exclude": "node_modules",
"generateScopedName": "[name]__[local]--[hash:base64:5]"
}
]
],

Any idea what's going wrong here?

 

Looks like you've got 'react-css-modules' as a plugin in your PostCSS config? It doesn't belong there, its just a Babel plugin.

 
 

I was looking for a way to have scoped styles that I could use by writing import styles from './my.css' and using them like className={styles.someClass}.

Without setting up anything further than was given here I made it. Any reason why you chose to use styleName? In my case, I'd rather stick to a well established attribute name. On the other hand, I can import more than one module to my components and use other styles. This is useful for when I have global styles that might apply in many places.

 

So styleName comes from the babel-plugin-react-css-modules plugin. Stolen from their docs:

However, there are several several disadvantages of using CSS modules this way:

  • You have to use camelCase CSS class names.
  • You have to use styles object whenever constructing a className.
  • Mixing CSS Modules and global CSS classes is cumbersome.
  • Reference to an undefined CSS Module resolves to undefined without a warning.

Using babel-plugin-react-css-modules:

  • You are not forced to use the camelCase naming convention.
  • You do not need to refer to the styles object every time you use a CSS Module.
  • There is clear distinction between global CSS and CSS modules, e.g.
<div className='global-css' styleName='local-module'></div>
 

BTW, CSS Modules is just a bunch of PostCSS plugins inside

 

👍 Didn't know that! Perhaps I should retitle post: "Other PostCSS plugins with CSS Modules and React"?

 

The article name is great ☺. It is just a curious fact.

BTW, css-loader is PostCSS plugins too 😄.

code of conduct - report abuse