CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-postcss-js

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

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

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"
}));

Install with Tessl CLI

npx tessl i tessl/npm-postcss-js
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/postcss-js@4.0.x
Publish Source
CLI
Badge
tessl/npm-postcss-js badge