By now, we've solved one of JavaScript biggest issues: modularity. There are a few major approaches to it, that is IIFEs, AMD, CommonJS and ES6 imports. Some of these are automatic, others rely on convention. The most future proof is ES6 imports, because it can be supported on the front- and back-end and is comfortable to use. Browsers are beginning to add native support for it and many tools recognize the ES6 imports syntax.
CSS is finally getting the same treatment.
CSS alone is not powerful enough to prevent serious styling collisions on websites. There have been multiple guides regarding using sane naming conventions that minimize this issue, but now there is a tool that can do it automatically for developers.
As JavaScript workflows have trended towards building collections of components, CSS workflows have followed suit. However, any progress on the CSS front has been purely conventional, not supported by the language.
Thanks to preprocessing tools, such as Webpack, PostCSS and CSS Modules, it's now possible to have modular CSS.
Unlike BEM and others, CSS Modules hashes class names based on a couple factors. For example, it may process a class name cart
to be cart__9SEMc
when referenced in HTML. The basic rule is to create unique hashes across files. This way, if there are two files using the same class name cart
but for different elements on a page, one name might be converted to cart__ABC2
and the other cart__72Ac
. In an overwhelming number of situations it does make sense to do so. But there's an escape hatch provided by CSS modules in the form of a :global
modifier, which allows to disable hashing.
While there may still exist collisions within a single file, files containing CSS don't usually get big enough for this to become a serious issue. My advice is to not use anything more than CSS modules as they are already enough of a help. However, it does play nice with convention-based CSS workflows.
It's important to note, that CSS modules will not in any way hash HTML tags and CSS IDs. Completely avoiding using these or nesting them inside CSS class names of parent elements will help.
Because CSS modules works on top of Webpack, getting original class names without hashes is insanely easy. Like any other module in Webpack, CSS processed with CSS modules can be imported. The import exposes all class names defined inside a file as a JavaScript object. So, in the case of cart
, all that's required is to import css from './cartComponent.css'
and then use the reference css.cart
, which evaluates to the hashed name.
In addition to class names, CSS modules can export variables to JavaScript with :export
. It's a neat feature, especially useful when animating an element with CSS and JavaScript at the same time, because it allows the timings of animations to be updated from a single place in the source code.