PostCSS plugin to use CSS Modules everywhere
npx @tessl/cli install tessl/npm-postcss-modules@6.0.00
# PostCSS Modules
1
2
PostCSS Modules is a PostCSS plugin that enables CSS Modules functionality everywhere, not just client-side applications. It transforms CSS classes into scoped, locally unique identifiers while preserving global styles where needed, providing automatic collision prevention and maintainable class name management.
3
4
## Package Information
5
6
- **Package Name**: postcss-modules
7
- **Package Type**: npm
8
- **Language**: JavaScript with TypeScript definitions
9
- **Installation**: `npm install postcss-modules`
10
11
## Core Imports
12
13
```javascript
14
const postcssModules = require("postcss-modules");
15
```
16
17
For TypeScript or ES modules:
18
19
```typescript
20
import postcssModules = require("postcss-modules");
21
// or with newer ES module support:
22
import postcssModules from "postcss-modules";
23
```
24
25
## Basic Usage
26
27
```javascript
28
const postcss = require("postcss");
29
const postcssModules = require("postcss-modules");
30
31
postcss([
32
postcssModules({
33
generateScopedName: "[name]__[local]___[hash:base64:5]",
34
getJSON: (cssFilename, json) => {
35
console.log("Generated mappings:", json);
36
}
37
})
38
])
39
.process(css, { from: cssFile })
40
.then(result => {
41
console.log(result.css); // Transformed CSS with scoped class names
42
});
43
```
44
45
## Architecture
46
47
PostCSS Modules is built around several key components:
48
49
- **Plugin Factory**: Main entry point that creates PostCSS plugin instances
50
- **File System Loader**: Handles CSS module imports and dependency resolution
51
- **Parser**: Processes CSS modules import/export syntax (`:import()` and `:export`)
52
- **Scoping System**: Generates unique class names and manages local/global behavior
53
- **Locals Convention**: Transforms class names according to naming conventions (camelCase, etc.)
54
55
## Capabilities
56
57
### Plugin Factory Function
58
59
Main plugin factory that creates a PostCSS plugin instance with the specified options.
60
61
```typescript { .api }
62
/**
63
* Creates a PostCSS plugin instance for CSS Modules processing
64
* @param options - Configuration options for the plugin
65
* @returns PostCSS plugin instance
66
*/
67
declare function postcssModules(options?: Options): Plugin;
68
69
/** PostCSS plugin identifier */
70
postcssModules.postcss: true;
71
72
interface Options {
73
/** Callback function to handle generated class name mappings */
74
getJSON?: (cssFilename: string, json: { [name: string]: string }, outputFilename?: string) => void;
75
76
/** Class name transformation convention */
77
localsConvention?: "camelCase" | "camelCaseOnly" | "dashes" | "dashesOnly" | LocalsConventionFunction;
78
79
/** Default scoping behavior for class names */
80
scopeBehaviour?: "global" | "local";
81
82
/** Array of regexes to match global module paths */
83
globalModulePaths?: RegExp[];
84
85
/** Custom scoped name generator */
86
generateScopedName?: string | GenerateScopedNameFunction;
87
88
/** Prefix for generated hash values */
89
hashPrefix?: string;
90
91
/** Whether to export global class names */
92
exportGlobals?: boolean;
93
94
/** Root directory for resolving imports */
95
root?: string;
96
97
/** Custom loader class for handling CSS module imports */
98
Loader?: typeof Loader;
99
100
/** Custom file resolver function */
101
resolve?: (file: string, importer: string) => string | null | Promise<string | null>;
102
}
103
```
104
105
**Usage Examples:**
106
107
```javascript
108
// Basic usage with string template for scoped names
109
postcssModules({
110
generateScopedName: "[name]__[local]___[hash:base64:5]"
111
})
112
113
// Custom scoped name generation function
114
postcssModules({
115
generateScopedName: (name, filename, css) => {
116
return `_${name}_${require('string-hash')(css).toString(36).substr(0, 5)}`;
117
}
118
})
119
120
// Handle generated mappings
121
postcssModules({
122
getJSON: (cssFilename, json, outputFilename) => {
123
fs.writeFileSync(cssFilename + '.json', JSON.stringify(json));
124
}
125
})
126
127
// Global module paths configuration
128
postcssModules({
129
globalModulePaths: [/node_modules/, /global\.css$/],
130
scopeBehaviour: "local"
131
})
132
```
133
134
### Scoped Name Generation
135
136
Controls how CSS class names are transformed into unique, scoped identifiers.
137
138
```typescript { .api }
139
/**
140
* Function type for custom scoped name generation
141
* @param name - Original CSS class name
142
* @param filename - CSS file path
143
* @param css - Complete CSS content
144
* @returns Generated scoped class name
145
*/
146
type GenerateScopedNameFunction = (name: string, filename: string, css: string) => string;
147
```
148
149
**String Template Format:**
150
- `[name]` - Original class name
151
- `[local]` - Alias for `[name]`
152
- `[hash]` - Hash of CSS content
153
- `[hash:base64:5]` - Base64 hash truncated to 5 characters
154
155
### Locals Convention
156
157
Transforms exported class names according to naming conventions for JavaScript consumption.
158
159
```typescript { .api }
160
/**
161
* Function type for custom locals convention transformation
162
* @param originalClassName - Original CSS class name
163
* @param generatedClassName - Generated scoped class name
164
* @param inputFile - CSS file path
165
* @returns Transformed class name for export
166
*/
167
type LocalsConventionFunction = (
168
originalClassName: string,
169
generatedClassName: string,
170
inputFile: string
171
) => string;
172
```
173
174
**Built-in Conventions:**
175
- `"camelCase"` - Exports both original and camelCase versions: `{ "btn-primary": "...", "btnPrimary": "..." }`
176
- `"camelCaseOnly"` - Exports only camelCase version: `{ "btnPrimary": "..." }`
177
- `"dashes"` - Exports both original and dash-converted versions
178
- `"dashesOnly"` - Exports only dash-converted versions
179
180
### File System Loader
181
182
Default loader implementation for handling CSS module imports and dependency resolution.
183
184
```typescript { .api }
185
/**
186
* Default file system loader for CSS modules
187
*/
188
declare class Loader {
189
/**
190
* Creates a new loader instance
191
* @param root - Root directory for resolving imports
192
* @param plugins - Array of PostCSS plugins to apply
193
* @param resolve - Optional custom file resolver function
194
*/
195
constructor(root: string, plugins: Plugin[], resolve?: (file: string, importer: string) => string | null | Promise<string | null>);
196
197
/**
198
* Fetches and processes a CSS module file
199
* @param file - File path to fetch
200
* @param relativeTo - Path to resolve relative imports from
201
* @param depTrace - Dependency trace for circular import detection
202
* @returns Promise resolving to class name mappings
203
*/
204
fetch(file: string, relativeTo: string, depTrace: string): Promise<{ [key: string]: string }>;
205
206
/** Combined final CSS source after processing all imports */
207
finalSource?: string;
208
}
209
```
210
211
### Core CSS Module Processor
212
213
Internal core processor class used by FileSystemLoader for handling CSS module transformations.
214
215
```typescript { .api }
216
/**
217
* Core CSS module processor that applies PostCSS transformations
218
*/
219
declare class Core {
220
/**
221
* Creates a new Core processor instance
222
* @param plugins - Array of PostCSS plugins to apply during processing
223
*/
224
constructor(plugins?: Plugin[]);
225
226
/**
227
* Loads and processes a CSS module file
228
* @param sourceString - CSS source code to process
229
* @param sourcePath - File path for the source (used for error reporting)
230
* @param trace - Dependency trace identifier for circular import detection
231
* @param pathFetcher - Function to fetch imported files
232
* @returns Promise resolving to processed CSS and export tokens
233
*/
234
load(
235
sourceString: string,
236
sourcePath: string,
237
trace: string,
238
pathFetcher: (file: string, relativeTo: string, depTrace: string) => Promise<{ [key: string]: string }>
239
): Promise<{
240
injectableSource: string;
241
exportTokens: { [key: string]: string };
242
}>;
243
244
/** Default plugins used when no plugins are specified */
245
static defaultPlugins?: Plugin[];
246
}
247
```
248
249
### Scoping Behaviors
250
251
Controls the default scoping behavior for CSS class names.
252
253
```typescript { .api }
254
/** Available scoping behaviors */
255
const behaviours = {
256
LOCAL: "local",
257
GLOBAL: "global"
258
} as const;
259
260
/**
261
* Gets default plugins for specified scoping behavior
262
* @param config - Scoping configuration
263
* @returns Array of PostCSS plugins
264
*/
265
function getDefaultPlugins(config: {
266
behaviour: "local" | "global";
267
generateScopedName: GenerateScopedNameFunction;
268
exportGlobals: boolean;
269
}): Plugin[];
270
271
/**
272
* Validates and returns scoping behavior, defaults to LOCAL
273
* @param scopeBehaviour - Desired scoping behavior
274
* @returns Valid scoping behavior
275
*/
276
function getDefaultScopeBehaviour(scopeBehaviour?: string): "local" | "global";
277
278
/**
279
* Creates or returns a scoped name generator function
280
* @param generateScopedName - String template or custom function for generating scoped names
281
* @param hashPrefix - Optional prefix for hash generation
282
* @returns Function that generates scoped class names
283
*/
284
function getScopedNameGenerator(
285
generateScopedName?: string | GenerateScopedNameFunction,
286
hashPrefix?: string
287
): GenerateScopedNameFunction;
288
```
289
290
## Types
291
292
```typescript { .api }
293
/** PostCSS Plugin interface */
294
interface Plugin {
295
postcssPlugin: string;
296
OnceExit?: (root: any, helpers: any) => void | Promise<void>;
297
}
298
```
299
300
## CSS Modules Syntax
301
302
PostCSS Modules processes special CSS syntax for imports and exports:
303
304
**Import Syntax:**
305
```css
306
:import("./other-module.css") {
307
imported-class: exported-class;
308
}
309
```
310
311
**Export Syntax:**
312
```css
313
:export {
314
localClass: scoped-class-name;
315
}
316
```
317
318
**Global/Local Selectors:**
319
```css
320
:global(.global-class) {
321
/* This class remains global */
322
}
323
324
:local(.local-class) {
325
/* This class gets scoped (default behavior) */
326
}
327
```
328
329
## Error Handling
330
331
The plugin may throw errors in the following cases:
332
333
- **Missing Plugin Error**: When the plugin is not found in the processor plugins list
334
- **Circular Import Error**: When CSS modules have circular dependencies
335
- **File Resolution Error**: When imported CSS files cannot be resolved or read
336
- **Invalid Hash Prefix Error**: When custom file resolvers return non-absolute paths