0
# PostCSS JS
1
2
PostCSS JS is a PostCSS integration library that enables the use of PostCSS plugins with CSS-in-JS and JavaScript style objects. It provides bidirectional conversion between CSS-in-JS objects and PostCSS AST, allowing developers to use the entire PostCSS ecosystem within JavaScript-based styling workflows.
3
4
## Package Information
5
6
- **Package Name**: postcss-js
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install postcss-js`
10
- **Peer Dependency**: `postcss@^8.4.21`
11
12
## Core Imports
13
14
```javascript
15
const postcssJs = require("postcss-js");
16
const { sync, async, parse, objectify } = require("postcss-js");
17
```
18
19
For ES modules:
20
21
```javascript
22
import postcssJs from "postcss-js";
23
import { sync, async, parse, objectify } from "postcss-js";
24
```
25
26
Individual module imports:
27
28
```javascript
29
const sync = require("postcss-js/sync");
30
const async = require("postcss-js/async");
31
const parse = require("postcss-js/parser");
32
const objectify = require("postcss-js/objectifier");
33
```
34
35
## Basic Usage
36
37
```javascript
38
const postcssJs = require("postcss-js");
39
const autoprefixer = require("autoprefixer");
40
41
// Create a synchronous processor
42
const prefixer = postcssJs.sync([autoprefixer]);
43
44
// Process CSS-in-JS objects
45
const style = prefixer({
46
userSelect: "none",
47
display: "flex"
48
});
49
50
// Result: {
51
// WebkitUserSelect: "none",
52
// MozUserSelect: "none",
53
// msUserSelect: "none",
54
// userSelect: "none",
55
// display: "flex"
56
// }
57
58
// Parse CSS-in-JS to PostCSS AST
59
const root = postcssJs.parse({
60
color: "red",
61
"&:hover": {
62
color: "blue"
63
}
64
});
65
66
// Convert PostCSS AST back to CSS-in-JS
67
const obj = postcssJs.objectify(root);
68
```
69
70
## Architecture
71
72
PostCSS JS is built around four core components:
73
74
- **Processors**: `sync` and `async` functions that create PostCSS processors for CSS-in-JS objects
75
- **Parser**: `parse` function that converts CSS-in-JS objects to PostCSS AST
76
- **Objectifier**: `objectify` function that converts PostCSS AST back to CSS-in-JS objects
77
- **Result Processing**: Internal utilities for handling PostCSS results and warnings
78
79
## Capabilities
80
81
### Synchronous Processing
82
83
Creates a synchronous PostCSS processor that works with CSS-in-JS objects and supports only synchronous PostCSS plugins.
84
85
```javascript { .api }
86
/**
87
* Create PostCSS processor with simple API, but with only sync PostCSS plugins support
88
* @param {Plugin[]} plugins - Array of PostCSS plugins (synchronous only)
89
* @returns {function} Processor function that takes a style object and returns processed object
90
*/
91
function sync(plugins);
92
```
93
94
**Usage Examples:**
95
96
```javascript
97
const postcssJs = require("postcss-js");
98
const autoprefixer = require("autoprefixer");
99
100
// Create processor with plugins
101
const processor = postcssJs.sync([autoprefixer]);
102
103
// Process style objects
104
const result = processor({
105
display: "flex",
106
userSelect: "none"
107
});
108
```
109
110
### Asynchronous Processing
111
112
Creates an asynchronous PostCSS processor that works with CSS-in-JS objects and supports both synchronous and asynchronous PostCSS plugins.
113
114
```javascript { .api }
115
/**
116
* Create PostCSS processor that supports both sync and async plugins
117
* @param {Plugin[]} plugins - Array of PostCSS plugins (sync and async)
118
* @returns {function} Async processor function that takes a style object and returns Promise<object>
119
*/
120
function async(plugins);
121
```
122
123
**Usage Examples:**
124
125
```javascript
126
const postcssJs = require("postcss-js");
127
const autoprefixer = require("autoprefixer");
128
129
// Create async processor
130
const processor = postcssJs.async([autoprefixer]);
131
132
// Process style objects (returns Promise)
133
const result = await processor({
134
display: "flex",
135
userSelect: "none"
136
});
137
```
138
139
### CSS-in-JS Parsing
140
141
Parses CSS-in-JS style objects into PostCSS Root instances, handling nested selectors, at-rules, and property conversions.
142
143
```javascript { .api }
144
/**
145
* Parse CSS-in-JS style object to PostCSS Root instance
146
* @param {Object} obj - CSS-in-JS style object
147
* @returns {Root} PostCSS Root instance
148
*/
149
function parse(obj);
150
```
151
152
**Key Features:**
153
- Converts camelCase properties to kebab-case (e.g., `userSelect` → `user-select`)
154
- Adds `px` suffix to numeric values (except for unitless properties)
155
- Handles nested selectors and at-rules
156
- Processes CSS custom properties (`--variables`) without name conversion, preserving exact syntax
157
- Supports `!important` declarations
158
- Handles array values for multiple declarations
159
160
**Usage Examples:**
161
162
```javascript
163
const postcss = require("postcss");
164
const postcssJs = require("postcss-js");
165
166
// Parse complex CSS-in-JS object
167
const root = postcssJs.parse({
168
color: "red",
169
fontSize: 16,
170
margin: [10, 20],
171
"--custom-prop": "#fff",
172
"&:hover": {
173
color: "blue"
174
},
175
"@media screen": {
176
fontSize: 18
177
}
178
});
179
180
// Use as PostCSS parser
181
const result = await postcss().process(styleObj, {
182
parser: postcssJs,
183
from: undefined
184
});
185
```
186
187
### PostCSS AST Objectification
188
189
Converts PostCSS Root instances back to CSS-in-JS style objects with proper property name and value conversions.
190
191
```javascript { .api }
192
/**
193
* Convert PostCSS Root instance to CSS-in-JS style object
194
* @param {Root} root - PostCSS Root instance
195
* @returns {Object} CSS-in-JS style object
196
*/
197
function objectify(root);
198
```
199
200
**Key Features:**
201
- Converts kebab-case properties to camelCase (e.g., `user-select` → `userSelect`)
202
- Converts numeric values for unitless properties to numbers
203
- Maintains CSS custom properties (`--variables`) without name conversion, preserving exact property names
204
- Handles nested rules and at-rules
205
- Supports multiple values as arrays
206
- Preserves `!important` declarations
207
208
**Usage Examples:**
209
210
```javascript
211
const postcss = require("postcss");
212
const postcssJs = require("postcss-js");
213
214
// Convert PostCSS AST to object
215
const css = "color: red; font-size: 16px; --theme-color: blue;";
216
const root = postcss.parse(css);
217
const obj = postcssJs.objectify(root);
218
219
// Result: {
220
// color: "red",
221
// fontSize: "16px",
222
// "--theme-color": "blue"
223
// }
224
```
225
226
## CSS Property Handling
227
228
### Unitless Properties
229
230
The following CSS properties are treated as unitless and numeric values are not converted to pixels. The parser uses kebab-case names while the objectifier uses camelCase names:
231
232
**Parser (kebab-case):**
233
```javascript { .api }
234
const PARSER_UNITLESS = {
235
"box-flex": true,
236
"box-flex-group": true,
237
"column-count": true,
238
"flex": true,
239
"flex-grow": true,
240
"flex-positive": true,
241
"flex-shrink": true,
242
"flex-negative": true,
243
"font-weight": true,
244
"line-clamp": true,
245
"line-height": true,
246
"opacity": true,
247
"order": true,
248
"orphans": true,
249
"tab-size": true,
250
"widows": true,
251
"z-index": true,
252
"zoom": true,
253
"fill-opacity": true,
254
"stroke-dashoffset": true,
255
"stroke-opacity": true,
256
"stroke-width": true
257
};
258
```
259
260
**Objectifier (camelCase):**
261
```javascript { .api }
262
const OBJECTIFIER_UNITLESS = {
263
boxFlex: true,
264
boxFlexGroup: true,
265
columnCount: true,
266
flex: true,
267
flexGrow: true,
268
flexPositive: true,
269
flexShrink: true,
270
flexNegative: true,
271
fontWeight: true,
272
lineClamp: true,
273
lineHeight: true,
274
opacity: true,
275
order: true,
276
orphans: true,
277
tabSize: true,
278
widows: true,
279
zIndex: true,
280
zoom: true,
281
fillOpacity: true,
282
strokeDashoffset: true,
283
strokeOpacity: true,
284
strokeWidth: true
285
};
286
```
287
288
### Property Name Conversion
289
290
- **Parsing (JS → CSS)**: camelCase → kebab-case (`userSelect` → `user-select`)
291
- **Objectifying (CSS → JS)**: kebab-case → camelCase (`user-select` → `userSelect`)
292
- **CSS Variables**: `--custom-properties` are preserved without conversion in both directions
293
- **Special Cases**:
294
- `cssFloat` (JS) ↔ `float` (CSS) - handles the reserved word conflict
295
- Properties in `:export` selectors preserve their original names without camelCase conversion
296
- Vendor prefixes like `-ms-transform` are handled correctly (camelCase: `msTransform`)
297
298
### Value Processing
299
300
- **Numeric Values**: Automatically appended with `px` unless property is unitless or value is `0`
301
- **Array Values**: Multiple values for the same property (e.g., `margin: [10, 20]`)
302
- **Important Declarations**: `!important` is parsed and preserved
303
- **Null/Undefined**: Filtered out during parsing
304
305
## Error Handling
306
307
PostCSS JS handles warnings and errors through:
308
309
- **Plugin Warnings**: Displayed via `console.warn` with plugin source identification
310
- **Parsing Errors**: Invalid CSS-in-JS structures are handled gracefully
311
- **Value Filtering**: `null` and `undefined` values are automatically filtered out
312
313
## Integration Patterns
314
315
### With PostCSS Plugins
316
317
```javascript
318
const postcssJs = require("postcss-js");
319
const autoprefixer = require("autoprefixer");
320
const cssnano = require("cssnano");
321
322
// Chain multiple plugins
323
const processor = postcssJs.sync([
324
autoprefixer({ browsers: ["last 2 versions"] }),
325
cssnano({ preset: "default" })
326
]);
327
```
328
329
### Custom PostCSS Parser
330
331
```javascript
332
const postcss = require("postcss");
333
const postcssJs = require("postcss-js");
334
335
// Use as custom parser
336
const result = await postcss([/* plugins */])
337
.process(cssInJsObject, {
338
parser: postcssJs,
339
from: undefined
340
});
341
```
342
343
### CSS-in-JS Library Integration
344
345
```javascript
346
// Works with any CSS-in-JS library
347
const styled = require("styled-components");
348
const postcssJs = require("postcss-js");
349
const autoprefixer = require("autoprefixer");
350
351
const prefixer = postcssJs.sync([autoprefixer]);
352
353
const Button = styled.button(prefixer({
354
display: "flex",
355
userSelect: "none"
356
}));
357
```