The combination of CSS Modules and PostCSS could be our new option

As a junior front-end developer I was using Sass for my entire career. Sass is super easy to write and it has many features which makes our front-end development more scalable, efficient and most importantly enjoyable :)

But recently more and more developers are considering CSS Modules or PostCSS in their products. That makes me curious about new way to style our product.

Unfortunately Sass is based on ruby. If we are on Ruby on Rails, Sass seems to be natural way for styling. Sprockets kindly deals with it instead of us. But what if we create our application by pure front-end stacks like React.js, Angular.js, Vue or Amber. We have to prepare gulp or grunt or something to convert Sass into CSS.

And secondly Sass seems to be “All in one” tool. Do we really need mixins or varibles in our every single application we create? After looking back to my career, I realized that only a few features like nesting or import are nessecary for styling.

So I tried CSS Modules and PostCSS in our product lately. Here is my impression about them and way to do it.

CSS Modules

I guess many developers already know CSS Modules. It’s kind of CSS in JS.

Here is a list of options which make CSS available in JavaScript.

And here goes an amazing post about comparison of CSS in JS and CSS Modules.

CSS in JS and CSS Modules are different in the point of how CSS exists. In CSS in JS world, CSS is written in JavaScript Object. It’s like immetation of <style />. By using CSS loader of Webpack we can import suchCSS-like objects into JavaScript. And styles are added as JSX’s inline style.

Yeah, that works! But I prefer CSS Modules because it creates whole new CSS files. Yes, we have to add one more <link /> to include CSS file — one more HTTP request. But it’s not inline styles anymore, which means that pseudo classes or media queries are available. This is a good news, isn’t it?

And the biggest benefit we can take is that CSS class names will be local scoped by using CSS Modules.

Let me show you code example and how it works later.

PostCSS, cssnext

So we decided to use CSS Modules. It’s not something like CSS-like objects. Row usual lovely CSS files. But some problems here. It’s CSS not Sass, so we can’t use nesting or import as natural.

Solution is PostCSS — more precisely, cssnext.

PostCSS is useful tool with many libraries like postcss-autoreset ,postcss-sorting and so on.

But to be honest I still don’t fully understand that usufulness. Because we decided to set standard for what we use. We are seeking features which are truly nessecary. Once installing as many PostCSS libraries as possible, it’s nothing but Sass. So this time we use only postcss-cssnext plugin.

Postcss-cssnext plugin is a converter for cssnext.

CSS next is a set of CSS features that is highly likely to be supported in the browsers in the near future.

The relationship between Postcss and cssnext is similar to the one between ES201* and Babel — Future language set and Transpiler.

Plan is ready, but how?

OK! Now we only use pure CSS with latest CSS features. It’s because of combination of CSS Modules and PostCSS.

But there’s no actual codes yet at all. From now description in detail starts.

packages

Here is a list of all packages for CSS Modules and Postcss.

We use Webpack and Babel as Front-end environment.

Config for CSS Modules

Ok, we have packages now. Let’s set up configuration for CSS Modules.

This is a partial of our webpack.config.js.

All we have to do is turing on Modules mode of css-loader by adding ‘modules’ query.

But this makes JavaScript create <style /> dynamicaly. So unfortunately there is a possibility to generate lag when rendering.

So we need to do one more thing. By using ExtractTextPlugin Webpack can generate new CSS file. It’s totally static and HTML can read it before rendering DOMs. No styling lag.

This config above means Webpack generates application.css.

And here is a CSS file we create and import in JavaScript.

And this is a React component of Button.

Styles can be accessed by hogeStyle.hoge.

But acctualy buttonStyle.button is like “.3d1CM”.

CSS class name is converted into Hash value that prevents from naming conflicts. So CSS is scoped locally by using CSS Modules.

application.css converted from button.css is like below.

And button.js component is converted like below.

Can you see that classname are match between CSS and HTML.

Converted classname is hash value. But we don’t have to care about it. Webpack, css-loader, ExtractTextPlugin take care of it instead of us.This is super easy, isn’t it??

Configure for PostCSS

OK, this time let’s add some lines in webpack.config.js.

We added two new things here.

One is adding ‘postcss’ loader after css-loader. To integrate them together importLoaders query for css-loader is necessary.

And another is postcss item for webpack config. And in postcss item we defined to use postcss-cssnext plugin.

That’s it! We can use cssnext in our CSS files now.

For example nesting is one of cssnext features. We add :hover style for Button.

This will be converted like below.

Postcss-cssnext plugin solves nesting into plain CSS.

css-loader queries

The basic explanation of CSS Modules and PostCSS is over. From now let’s take a look at some tips.

I know some people don’t like string query for webpack loaders. We can define queries separately like below.

Yeah, it looks smarter. But unfortunately ExtractTextPlugin.extract function return loaders. Not singular. We can’t use query key for multile loaders.

So as a workaround I defined queries before configs.

Got better I guess.

Other css-loader options

The css-loader has other options. Here is sample queries we use in our production.

camelCase is so usuful. We prefer class names chained by hyphens like ‘hoge-container’. But you know we can’t use that case in JavaScript. So camelCase option makes css-loader convert case of class names.

As you can imagine sourceMap enables us to see sourcemap.

localIdentName is option to determine the form of converted class name. As default in CSS Modules’ world class names will be converted to only hash values. But this is not good for humans. By configuring like above converted class names will be like ‘button-primary-2N09e’. [name] means CSS file name, [local] is class name and [hash:base64:5] is hash value.

Conclusion

To use CSS Modules and PostCSS we have to do some setups as you see in this post. And knowledge about webpack or npm is required. Plus so far I couldn’t find other way to do this but webpack. Dependency on Webpack may be too strong? Some developers doesn’t accept this, I know.

But CSS Modules and PostCSS together could be the one of options to style, like Sass is. I reccomend Front-end developers to know there is a option like this and try it at least once. But for Server-side developers and Designers who write CSS it’s bit hard to spend their time on learning them…

So important thing is “Don’t rely on Sass with no considering. Consider and have conversation in your team if CSS Modules and PostCSS can suit in your product”.

Sample codes are in my Github repo.

Please check it for full files.

CSS Modules or PostCSS references

http://glenmaddern.com/articles/css-modules

https://medium.com/@pioul/modular-css-with-react-61638ae9ea3e#.blpcd13lf