Top Related Projects
Documentation about css-modules
CSS Loader
Quick Overview
postcss-modules is a PostCSS plugin that transforms CSS Modules into a format that can be used by JavaScript. It allows for local scope CSS by default and generates a JSON file with the mappings of classnames, making it easier to use CSS Modules in various JavaScript environments.
Pros
- Enables local scoping of CSS classes by default, reducing naming conflicts
- Generates a JSON file with class name mappings for easy integration with JavaScript
- Supports custom naming patterns for generated class names
- Compatible with various build tools and frameworks
Cons
- Requires additional setup and configuration compared to traditional CSS
- May have a slight learning curve for developers new to CSS Modules
- Can increase build time due to the additional processing step
- Might not be necessary for smaller projects or teams with strict naming conventions
Code Examples
- Basic usage with PostCSS:
const postcss = require('postcss');
const postcssModules = require('postcss-modules');
postcss([
postcssModules({
generateScopedName: '[name]__[local]___[hash:base64:5]',
})
]).process(css);
- Customizing the generated JSON output:
postcssModules({
getJSON: function (cssFileName, json, outputFileName) {
const path = require('path');
const cssName = path.basename(cssFileName, '.css');
const jsonFileName = path.resolve('./build/' + cssName + '.json');
fs.writeFileSync(jsonFileName, JSON.stringify(json));
}
})
- Using with Webpack:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
},
},
'postcss-loader',
],
},
],
},
};
Getting Started
-
Install the package:
npm install --save-dev postcss postcss-modules
-
Add it to your PostCSS config (postcss.config.js):
module.exports = { plugins: [ require('postcss-modules')({ generateScopedName: '[name]__[local]___[hash:base64:5]', }), ], };
-
Use in your CSS files:
/* styles.css */ .button { background: blue; }
-
Import and use in your JavaScript:
import styles from './styles.css'; const button = document.createElement('button'); button.className = styles.button;
Competitor Comparisons
Documentation about css-modules
Pros of css-modules
- More comprehensive documentation and examples
- Broader community support and adoption
- Language-agnostic approach, not tied to a specific implementation
Cons of css-modules
- Less focused on PostCSS integration
- May require additional setup and configuration
- Not as lightweight as postcss-modules
Code Comparison
css-modules:
.className {
color: green;
}
:global(.globalClassName) {
color: red;
}
postcss-modules:
.className {
color: green;
}
:global {
.globalClassName {
color: red;
}
}
Both approaches achieve similar results, but postcss-modules uses a slightly different syntax for global styles. The css-modules example is more widely recognized and used across different implementations.
css-modules provides a specification that can be implemented in various ways, while postcss-modules is a specific PostCSS plugin. This means css-modules offers more flexibility in terms of implementation and integration with different build systems.
However, postcss-modules is more straightforward to set up if you're already using PostCSS in your project. It provides a simpler API and integrates seamlessly with other PostCSS plugins.
Ultimately, the choice between the two depends on your specific project requirements, existing toolchain, and preference for either a more standardized approach (css-modules) or a PostCSS-specific solution (postcss-modules).
CSS Loader
Pros of css-loader
- Integrated with webpack ecosystem, providing seamless compatibility with other loaders
- Supports various CSS preprocessing options out-of-the-box
- Handles asset resolution and url() rewriting automatically
Cons of css-loader
- Can be more complex to configure, especially for beginners
- May have slower build times for large projects due to its comprehensive feature set
- Less focused on CSS Modules specifically, as it's a more general-purpose CSS loader
Code Comparison
css-loader:
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
postcss-modules:
const postcss = require('postcss');
const cssModules = require('postcss-modules');
postcss([cssModules()])
.process(css, { from: 'src/app.css', to: 'dist/app.css' })
.then(result => {
console.log(result.css);
});
Summary
While css-loader offers a more comprehensive solution for handling CSS in webpack projects, postcss-modules focuses specifically on implementing CSS Modules. css-loader provides broader functionality but may be more complex, while postcss-modules offers a simpler, more targeted approach to CSS Modules implementation.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
postcss-modules
A PostCSS plugin to use CSS Modules everywhere. Not only at the client side.
What is this?
For example, you have the following CSS:
/* styles.css */
:global .page {
padding: 20px;
}
.title {
composes: title from "./mixins.css";
color: green;
}
.article {
font-size: 16px;
}
/* mixins.css */
.title {
color: black;
font-size: 40px;
}
.title:hover {
color: red;
}
After the transformation it will become like this:
._title_116zl_1 {
color: black;
font-size: 40px;
}
._title_116zl_1:hover {
color: red;
}
.page {
padding: 20px;
}
._title_xkpkl_5 {
color: green;
}
._article_xkpkl_10 {
font-size: 16px;
}
And the plugin will give you a JSON object for transformed classes:
{
"title": "_title_xkpkl_5 _title_116zl_1",
"article": "_article_xkpkl_10"
}
Usage
Saving exported classes
By default, a JSON file with exported classes will be placed next to corresponding CSS.
But you have a freedom to make everything you want with exported classes, just
use the getJSON
callback. For example, save data about classes into a corresponding JSON file:
postcss([
require("postcss-modules")({
getJSON: function (cssFileName, json, outputFileName) {
var path = require("path");
var cssName = path.basename(cssFileName, ".css");
var jsonFileName = path.resolve("./build/" + cssName + ".json");
fs.writeFileSync(jsonFileName, JSON.stringify(json));
},
}),
]);
getJSON
may also return a Promise
.
Generating scoped names
By default, the plugin assumes that all the classes are local. You can change
this behaviour using the scopeBehaviour
option:
postcss([
require("postcss-modules")({
scopeBehaviour: "global", // can be 'global' or 'local',
}),
]);
To define paths for global modules, use the globalModulePaths
option.
It is an array with regular expressions defining the paths:
postcss([
require('postcss-modules')({
globalModulePaths: [/path\/to\/legacy-styles/, /another\/paths/],
});
]);
To generate custom classes, use the generateScopedName
callback:
postcss([
require("postcss-modules")({
generateScopedName: function (name, filename, css) {
var path = require("path");
var i = css.indexOf("." + name);
var line = css.substr(0, i).split(/[\r\n]/).length;
var file = path.basename(filename, ".css");
return "_" + file + "_" + line + "_" + name;
},
}),
]);
Or just pass an interpolated string to the generateScopedName
option
(More details here):
postcss([
require("postcss-modules")({
generateScopedName: "[name]__[local]___[hash:base64:5]",
}),
]);
It's possible to add custom hash to generate more unique classes using the hashPrefix
option (like in css-loader):
postcss([
require("postcss-modules")({
generateScopedName: "[name]__[local]___[hash:base64:5]",
hashPrefix: "prefix",
}),
]);
Exporting globals
If you need to export global names via the JSON object along with the local ones, add the exportGlobals
option:
postcss([
require("postcss-modules")({
exportGlobals: true,
}),
]);
Loading source files
If you need, you can pass a custom loader (see FileSystemLoader for example):
postcss([
require("postcss-modules")({
Loader: CustomLoader,
}),
]);
You can also pass any needed root path:
postcss([
require('postcss-modules')({
root: 'C:\\',
});
]);
localsConvention
Type: String | (originalClassName: string, generatedClassName: string, inputFile: string) => className: string
Default: null
Style of exported classnames, the keys in your json.
Name | Type | Description |
---|---|---|
'camelCase' | {String} | Class names will be camelized, the original class name will not to be removed from the locals |
'camelCaseOnly' | {String} | Class names will be camelized, the original class name will be removed from the locals |
'dashes' | {String} | Only dashes in class names will be camelized |
'dashesOnly' | {String} | Dashes in class names will be camelized, the original class name will be removed from the locals |
In lieu of a string, a custom function can generate the exported class names.
Resolve path alias
You can rewrite paths for composes/from
by using the resolve
option.
It's useful when you need to resolve custom path alias.
Parameters:
file
â a module we want to resolveimporter
â the file that imports the module we want to resolve
Return value: string | null | Promise<string | null>
postcss([
require("postcss-modules")({
resolve: function (file, importer) {
return path.resolve(
path.dirname(importer),
file.replace(/^@/, process.cwd()
);
},
}),
]);
Integration with templates
The plugin only transforms CSS classes to CSS modules. But you probably want to integrate these CSS modules with your templates. Here are some examples.
Assume you've saved project's CSS modules in cssModules.json
:
{
"title": "_title_xkpkl_5 _title_116zl_1",
"article": "_article_xkpkl_10"
}
Pug (ex-Jade)
Let's say you have a Pug template about.jade
:
h1(class=css.title) postcss-modules
article(class=css.article) A PostCSS plugin to use CSS Modules everywhere
Render it:
var jade = require("jade");
var cssModules = require("./cssModules.json");
var html = jade.compileFile("about.jade")({ css: cssModules });
console.log(html);
And you'll get the following HTML:
<h1 class="_title_xkpkl_5 _title_116zl_1">postcss-modules</h1>
<article class="_article_xkpkl_10">
A PostCSS plugin to use CSS Modules everywhere
</article>
HTML
For HTML transformation we'll use PostHTML and PostHTML CSS Modules:
npm install --save posthtml posthtml-css-modules
Here is our template about.html
:
<h1 css-module="title">postcss-modules</h1>
<article css-module="article">
A PostCSS plugin to use CSS Modules everywhere
</article>
Transform it:
var fs = require("fs");
var posthtml = require("posthtml");
var posthtmlCssModules = require("posthtml-css-modules");
var template = fs.readFileSync("./about.html", "utf8");
posthtml([posthtmlCssModules("./cssModules.json")])
.process(template)
.then(function (result) {
console.log(result.html);
});
(for using other build systems please check the documentation of PostHTML)
And you'll get the following HTML:
<h1 class="_title_xkpkl_5 _title_116zl_1">postcss-modules</h1>
<article class="_article_xkpkl_10">
A PostCSS plugin to use CSS Modules everywhere
</article>
May I see the plugin in action?
Sure! Take a look at the example.
See PostCSS docs for examples for your environment and don't forget to run
npm install --save-dev postcss postcss-modules
Sponsors
- Dmitry Olyenyov
Top Related Projects
Documentation about css-modules
CSS Loader
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot