or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

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

index.mddocs/

PostCSS JS

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.

Package Information

  • Package Name: postcss-js
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install postcss-js
  • Peer Dependency: postcss@^8.4.21

Core Imports

const postcssJs = require("postcss-js");
const { sync, async, parse, objectify } = require("postcss-js");

For ES modules:

import postcssJs from "postcss-js";
import { sync, async, parse, objectify } from "postcss-js";

Individual module imports:

const sync = require("postcss-js/sync");
const async = require("postcss-js/async");  
const parse = require("postcss-js/parser");
const objectify = require("postcss-js/objectifier");

Basic Usage

const postcssJs = require("postcss-js");
const autoprefixer = require("autoprefixer");

// Create a synchronous processor
const prefixer = postcssJs.sync([autoprefixer]);

// Process CSS-in-JS objects
const style = prefixer({
  userSelect: "none",
  display: "flex"
});

// Result: {
//   WebkitUserSelect: "none",
//   MozUserSelect: "none",
//   msUserSelect: "none",
//   userSelect: "none",
//   display: "flex"
// }

// Parse CSS-in-JS to PostCSS AST
const root = postcssJs.parse({
  color: "red",
  "&:hover": {
    color: "blue"
  }
});

// Convert PostCSS AST back to CSS-in-JS
const obj = postcssJs.objectify(root);

Architecture

PostCSS JS is built around four core components:

  • Processors: sync and async functions that create PostCSS processors for CSS-in-JS objects
  • Parser: parse function that converts CSS-in-JS objects to PostCSS AST
  • Objectifier: objectify function that converts PostCSS AST back to CSS-in-JS objects
  • Result Processing: Internal utilities for handling PostCSS results and warnings

Capabilities

Synchronous Processing

Creates a synchronous PostCSS processor that works with CSS-in-JS objects and supports only synchronous PostCSS plugins.

/**
 * Create PostCSS processor with simple API, but with only sync PostCSS plugins support
 * @param {Plugin[]} plugins - Array of PostCSS plugins (synchronous only)
 * @returns {function} Processor function that takes a style object and returns processed object
 */
function sync(plugins);

Usage Examples:

const postcssJs = require("postcss-js");
const autoprefixer = require("autoprefixer");

// Create processor with plugins
const processor = postcssJs.sync([autoprefixer]);

// Process style objects
const result = processor({
  display: "flex",
  userSelect: "none"
});

Asynchronous Processing

Creates an asynchronous PostCSS processor that works with CSS-in-JS objects and supports both synchronous and asynchronous PostCSS plugins.

/**
 * Create PostCSS processor that supports both sync and async plugins
 * @param {Plugin[]} plugins - Array of PostCSS plugins (sync and async)
 * @returns {function} Async processor function that takes a style object and returns Promise<object>
 */
function async(plugins);

Usage Examples:

const postcssJs = require("postcss-js");
const autoprefixer = require("autoprefixer");

// Create async processor
const processor = postcssJs.async([autoprefixer]);

// Process style objects (returns Promise)
const result = await processor({
  display: "flex",
  userSelect: "none"
});

CSS-in-JS Parsing

Parses CSS-in-JS style objects into PostCSS Root instances, handling nested selectors, at-rules, and property conversions.

/**
 * Parse CSS-in-JS style object to PostCSS Root instance
 * @param {Object} obj - CSS-in-JS style object
 * @returns {Root} PostCSS Root instance
 */
function parse(obj);

Key Features:

  • Converts camelCase properties to kebab-case (e.g., userSelectuser-select)
  • Adds px suffix to numeric values (except for unitless properties)
  • Handles nested selectors and at-rules
  • Processes CSS custom properties (--variables) without name conversion, preserving exact syntax
  • Supports !important declarations
  • Handles array values for multiple declarations

Usage Examples:

const postcss = require("postcss");
const postcssJs = require("postcss-js");

// Parse complex CSS-in-JS object
const root = postcssJs.parse({
  color: "red",
  fontSize: 16,
  margin: [10, 20],
  "--custom-prop": "#fff",
  "&:hover": {
    color: "blue"
  },
  "@media screen": {
    fontSize: 18
  }
});

// Use as PostCSS parser
const result = await postcss().process(styleObj, { 
  parser: postcssJs,
  from: undefined 
});

PostCSS AST Objectification

Converts PostCSS Root instances back to CSS-in-JS style objects with proper property name and value conversions.

/**
 * Convert PostCSS Root instance to CSS-in-JS style object
 * @param {Root} root - PostCSS Root instance
 * @returns {Object} CSS-in-JS style object
 */
function objectify(root);

Key Features:

  • Converts kebab-case properties to camelCase (e.g., user-selectuserSelect)
  • Converts numeric values for unitless properties to numbers
  • Maintains CSS custom properties (--variables) without name conversion, preserving exact property names
  • Handles nested rules and at-rules
  • Supports multiple values as arrays
  • Preserves !important declarations

Usage Examples:

const postcss = require("postcss");
const postcssJs = require("postcss-js");

// Convert PostCSS AST to object
const css = "color: red; font-size: 16px; --theme-color: blue;";
const root = postcss.parse(css);
const obj = postcssJs.objectify(root);

// Result: {
//   color: "red",
//   fontSize: "16px", 
//   "--theme-color": "blue"
// }

CSS Property Handling

Unitless Properties

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:

Parser (kebab-case):

const PARSER_UNITLESS = {
  "box-flex": true,
  "box-flex-group": true,
  "column-count": true,
  "flex": true,
  "flex-grow": true,
  "flex-positive": true,
  "flex-shrink": true,
  "flex-negative": true,
  "font-weight": true,
  "line-clamp": true,
  "line-height": true,
  "opacity": true,
  "order": true,
  "orphans": true,
  "tab-size": true,
  "widows": true,
  "z-index": true,
  "zoom": true,
  "fill-opacity": true,
  "stroke-dashoffset": true,
  "stroke-opacity": true,
  "stroke-width": true
};

Objectifier (camelCase):

const OBJECTIFIER_UNITLESS = {
  boxFlex: true,
  boxFlexGroup: true,
  columnCount: true,
  flex: true,
  flexGrow: true,
  flexPositive: true,
  flexShrink: true,
  flexNegative: true,
  fontWeight: true,
  lineClamp: true,
  lineHeight: true,
  opacity: true,
  order: true,
  orphans: true,
  tabSize: true,
  widows: true,
  zIndex: true,
  zoom: true,
  fillOpacity: true,
  strokeDashoffset: true,
  strokeOpacity: true,
  strokeWidth: true
};

Property Name Conversion

  • Parsing (JS → CSS): camelCase → kebab-case (userSelectuser-select)
  • Objectifying (CSS → JS): kebab-case → camelCase (user-selectuserSelect)
  • CSS Variables: --custom-properties are preserved without conversion in both directions
  • Special Cases:
    • cssFloat (JS) ↔ float (CSS) - handles the reserved word conflict
    • Properties in :export selectors preserve their original names without camelCase conversion
    • Vendor prefixes like -ms-transform are handled correctly (camelCase: msTransform)

Value Processing

  • Numeric Values: Automatically appended with px unless property is unitless or value is 0
  • Array Values: Multiple values for the same property (e.g., margin: [10, 20])
  • Important Declarations: !important is parsed and preserved
  • Null/Undefined: Filtered out during parsing

Error Handling

PostCSS JS handles warnings and errors through:

  • Plugin Warnings: Displayed via console.warn with plugin source identification
  • Parsing Errors: Invalid CSS-in-JS structures are handled gracefully
  • Value Filtering: null and undefined values are automatically filtered out

Integration Patterns

With PostCSS Plugins

const postcssJs = require("postcss-js");
const autoprefixer = require("autoprefixer");
const cssnano = require("cssnano");

// Chain multiple plugins
const processor = postcssJs.sync([
  autoprefixer({ browsers: ["last 2 versions"] }),
  cssnano({ preset: "default" })
]);

Custom PostCSS Parser

const postcss = require("postcss");
const postcssJs = require("postcss-js");

// Use as custom parser
const result = await postcss([/* plugins */])
  .process(cssInJsObject, { 
    parser: postcssJs,
    from: undefined 
  });

CSS-in-JS Library Integration

// Works with any CSS-in-JS library
const styled = require("styled-components");
const postcssJs = require("postcss-js");
const autoprefixer = require("autoprefixer");

const prefixer = postcssJs.sync([autoprefixer]);

const Button = styled.button(prefixer({
  display: "flex",
  userSelect: "none"
}));