or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-postcss-js

PostCSS integration library for CSS-in-JS and JavaScript style objects with bidirectional conversion capabilities

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/postcss-js@4.0.x

To install, run

npx @tessl/cli install tessl/npm-postcss-js@4.0.0

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

```