An all-in-one CSS parsing solution for Node.js and the browser, covering parsing, validation, transformation, minification, and AST-based tooling.
The library always fully parses the stylesheet into a structured AST, and token values are exposed as typed data so custom transforms, plugins, and analysis can work with reliable, semantic input instead of raw strings.
From npm
$ npm install @tbela99/css-parserfrom jsr
$ deno add @tbela99/css-parser- Zero dependencies — lightweight and easy to integrate into any project.
- All-in-one CSS parsing solution covering parsing, validation, transformation, minification, and AST manipulation.
- Standards-based CSS validation powered by MDN data.
- Full CSS Modules support for modern component-based workflows.
- Fault-tolerant parsing that follows the CSS Syntax Module Level 3 specification and always produces a complete, structured parse result.
- Typed tokens and AST — parsed CSS is exposed as strongly typed tokens and nodes so plugins and transforms can operate on semantic structures.
- High-performance minification with safe optimizations and no unsafe transforms.
- Advanced color processing with support for modern color spaces and functions, including
color(),lab(),lch(),oklab(),oklch(),color-mix(),light-dark(), system colors, and relative colors. - Color conversion engine capable of transforming colors between all supported formats.
- Automatic CSS nesting generation from compatible selectors.
- Source map generation for easier debugging and development workflows.
- Shorthand property computation to reduce output size and improve optimization.
- Transform function optimization for more compact CSS output.
- Math function evaluation, including
calc(),clamp(),min(),max(), and related expressions. - CSS variable inlining where values can be safely resolved.
- Duplicate declaration removal to eliminate redundant rules.
@importflattening to produce self-contained stylesheets.
Vendor prefix cleanup to modernize generated CSS.
CSS-Parser can transform these modern CSS features into lower-level CSS syntax:
- Nested CSS transpilation to legacy-compatible syntax.
if()function transpilation for broader browser compatibility.color-mix()function conversion convert new color-mix() syntax to any of the supported colors.
Across all tested datasets, css-parser consistently produces the smallest output among the benchmarked tools, including Lightning CSS, cssnano, csso, clean-css, css-tree, and esbuild.
The benchmark evaluates minification effectiveness on a diverse set of real-world stylesheets, including Bootstrap 4, Bootstrap 5, Tailwind CSS, Animate.css, Foundation, Font Awesome, Normalize.css, and others.
A sample result:
| File | ligthningcss | CSS Parser |
|---|---|---|
| tailwind.css - 2380419 bytes | 1864728 bytes | 1633188 bytes |
| bootstrap-4.css - 200078 bytes | 153616 bytes | 144571 bytes |
| bootstrap-5.css - 205481 bytes | 159987 bytes | 150852 bytes |
On the complete benchmark suite, css-parser generated a total output size of 2,158,698 bytes, compared to 2,494,113 bytes for Lightning CSS and larger outputs for all other tested minifiers. While some tools prioritize raw execution speed, css-parser focuses on maximizing compression while preserving stylesheet semantics, resulting in consistently smaller production bundles.
css-parser is designed for maximum minification performance, but the optimal configuration depends on what matters most for your workload.
The parser provides settings that let you choose the balance between minification performance and execution speed:
-
Minification performance: prioritize the quality and efficiency of the minification process, allowing the parser to perform additional work when generating the minimized output.
-
Execution speed: minimize the amount of work performed during parsing and minification to achieve the fastest possible execution time.
However, the available settings allow you to shift the balance toward execution speed when minimizing runtime is more important than performing every available minification optimization.
The example below demonstrates a balanced configuration that improves execution speed by disabling advanced minification features.
import {transformSync} from "@tbela99/css-parser";
const css = `...`;
const result = transformSync({
input: css,
minify: false,
beautify: false,
removeEmpty: true,
removeComments: true,
convertColor: true,
minifyValues: true,
});
console.debug(result.code);
console.debug(result.stats);Performance vs execution speed comparison
| File: tailwind.css | Speed optimization | Minification optimization |
|---|---|---|
| Size: 2,380,419 bytes | 1,890,728 bytes | 1,633,188 bytes |
| Time | 205.91 ms | 471.89 ms |
| Size reduction | -20.6% | -31.4% |
Try it online
- Installation
- Usage
- Validation
- CSS Modules
- Minification
- Custom Transform
- Sourcemap
- Plugins API
- Syntax Lowering
- Prefix Removal
- Ast Manipulation
- Utility Functions
- typ: number
- val: string, the comment
- typ: number
- chi: array of children
- typ: number
- nam: string, declaration name
- val: array of tokens
- state: EnumAstNodeStatus, validation state
- errors: ErrorDescription[], validation errors
- typ: number
- sel: string, css selector
- chi: array of children
- state: EnumAstNodeStatus, validation state
- errors: ErrorDescription[], validation errors
- typ: number
- nam: string. AtRule name
- val: rule prelude
- state: EnumAstNodeStatus, validation state
- errors: ErrorDescription[], validation errors
- typ: number
- sel: string, css selector
- chi: array of children
- state: EnumAstNodeStatus, validation state
- errors: ErrorDescription[], validation errors
- Sourcemap generation
- Input sourcemap: when the input CSS comes from another tool, you can pass the sourcemap content to link the generated CSS positions to the original files.
-
all - animation
- background
- border
- border-block-end
- border-block-start
- border-bottom
- border-color
- border-image
- border-inline-end
- border-inline-start
- border-left
- border-radius
- border-right
- border-style
- border-top
- border-width
- column-rule
- columns
- container
- contain-intrinsic-size
- flex
- flex-flow
- font
- font-synthesis
- font-variant
- gap
- grid
- grid-area
- grid-column
- grid-row
- grid-template
- inset
- list-style
- margin
- mask
- offset
- outline
- overflow
- padding
- place-content
- place-items
- place-self
- scroll-margin
- scroll-padding
- scroll-timeline
- text-decoration
- text-emphasis
- transition
- Bundle file referenced by the @import statement.
flowchart TD
%% --- Transform ---
Input(["CSS input"])
%% The Grouped Container
subgraph Group10["Transform step"]
transform["transform()/transformSync()"]
%% The Grouped Container
subgraph Group1 ["Parse step"]
%% --- Parse step ---
parse["parse()/parseSync()"]
tokenize(["tokenize()"])
parseNode(["parse and validate token stream"])
visitors(["visitors"])
minify(["minify AST"])
cssModules(["generate CSS module"])
parseResult["Parse result"]
end
%% The Grouped Container
subgraph Group2 ["Render step"]
%% --- Render step ---
renderAst(["Render AST"])
sourcemap([Sourcemap generation])
end
%% --- Result step ---
transformResult["Transform result"]
end
%% --- Routing step ---
Input --> transform
transform --> parse
parse --> tokenize
tokenize --> parseNode
parseNode -- "Visitors set?" --> visitors
visitors -- "Minify AST?" --> minify
minify -- "CSS module?" --> cssModules
visitors -- "CSS module?" --> cssModules
cssModules --> parseResult
parseNode -- "CSS module?" --> cssModules
parseNode -- "Minify AST?" --> minify
parseNode --> parseResult
visitors --> parseResult
minify --> parseResult
parseResult --> renderAst
renderAst -- "Sourcemap?" --> sourcemap
renderAst --> transformResult
sourcemap --> transformResult