What is css-tree?
The css-tree npm package is a tool for parsing and manipulating CSS. It allows users to parse CSS strings into an abstract syntax tree (AST), walk over nodes in the tree, generate CSS strings, and more. It is useful for tasks such as CSS minification, linting, and transformation.
What are css-tree's main functionalities?
Parsing CSS to AST
This feature allows you to parse a CSS string and convert it into an abstract syntax tree (AST) for further manipulation or analysis.
const csstree = require('css-tree');
const ast = csstree.parse('.example { color: red; }');
Walking the AST
This feature enables you to traverse the AST and apply functions or extract information from specific nodes.
csstree.walk(ast, function(node) {
if (node.type === 'ClassSelector') {
console.log(node.name);
}
});
Generating CSS from AST
After manipulating the AST, you can generate a CSS string from the modified AST, which can be used in stylesheets or injected into web pages.
const modifiedAST = csstree.parse('.example { color: blue; }');
const css = csstree.generate(modifiedAST);
Minifying CSS
css-tree can be used to minify CSS by parsing it with compression options and then translating the AST back to a CSS string.
const compressedCSS = csstree.translate(csstree.parse('.example { color: red; }', { compress: true }));
Other packages similar to css-tree
postcss
PostCSS is a tool for transforming CSS with JavaScript plugins. It can do similar tasks as css-tree, such as parsing, walking the AST, and generating CSS. PostCSS is plugin-based, which makes it more extensible and allows for a wide range of transformations.
sass
Sass is a preprocessor scripting language that is interpreted or compiled into CSS. It offers more syntactic features compared to css-tree, such as variables, nesting, and mixins, but it is not primarily focused on parsing and manipulating existing CSS.
less
Less is another CSS pre-processor, similar to Sass, that extends the capabilities of CSS with dynamic behavior such as variables, mixins, operations, and functions. Less and css-tree serve different purposes, with Less focusing on writing CSS in a more functional way and css-tree on parsing and manipulation.
clean-css
clean-css is a fast and efficient CSS optimizer for Node.js and the browser. It focuses on minification, which is one of the features of css-tree, but does not provide a general-purpose CSS parsing and manipulation API.

CSSTree

The set of tools for working with CSS, including fast detailed parser (string->AST), walkers, generators (AST->string) and even lexer (validation and matching) based on knowledge of spec and browser implementations (see schema for details). The main goal to be efficient and W3C spec complient, with focus on analyzing and source-to-source processing.
Work in progress. The project in alpha stage since some parts need further experiments, AST format and API are subjects to change. However it's stable enough and used by packages like CSSO (CSS minifier) in production.
Docs and tools:
Related projects:
Install
> npm install css-tree
Usage
var csstree = require('css-tree');
var ast = csstree.parse('.example { world: "!" }');
csstree.walk(ast, function(node) {
if (node.type === 'ClassSelector' && node.name === 'example') {
node.name = 'hello';
}
});
console.log(csstree.translate(ast));
Top level API

License
MIT
Syntax matching uses mdn/data by Mozilla Contributors
1.0.0-alpha20 (August 28, 2017)
- Tokenizer
- Added
Atrule
token type (<at-rule-token>
per spec)
- Added
Function
token type (<function-token>
per spec)
- Added
Url
token type
- Replaced
Tokenizer#getTypes()
method with Tokenizer#dump()
to get all tokens as an array
- Renamed
Tokenizer.TYPE.Whitespace
to Tokenizer.TYPE.WhiteSpace
- Renamed
Tokenizer.findWhitespaceEnd()
to Tokenizer.findWhiteSpaceEnd()
- Parser
- Added initial implementation of tollerant mode (turn on by passing
tolerant: true
option). In this mode parse errors are never occour and any invalid part of CSS turns into a Raw
node. Current safe points: Atrule
, AtruleExpression
, Rule
, Selector
and Declaration
. Feature is experimental and further improvements are planned.
- Changed
Atrule.expression
to contain a AtruleExpression
node or null
only (other node types is wrapping into a AtruleExpression
node)
- Renamed
AttributeSelector.operator
to AttributeSelector.matcher
- Generator
translate()
method is now can take a function as second argument, that recieves every generated chunk. When no function is passed, default handler is used, it concats all the chunks and method returns a string.
- Lexer
- Used mdn/data package as source of lexer's grammar instead of local dictionaries
- Added
x
unit to <resolution>
generic type
- Improved match tree:
- Omited Group (sequences) match nodes
- Omited empty match nodes (for terms with
zero or more
multipliers)
- Added
ASTNode
node type to contain a reference to AST node
- Fixed node duplication (uncompleted match were added to tree)
- Added AST node reference in match nodes
- Added comma match node by
#
multiplier
- Grammar
- Changed
translate()
function to get a handler as third argument (optional). That handler recieves result of node traslation and can be used for decoration purposes. See example
- Added
SyntaxParseError
to grammar export
- Reworked group and multipliers representation in syntax tree:
- Replaced
Sequence
for Group
node type (Sequence
node type removed)
- Added
explicit
boolean property for Group
- Only groups can have a multiplier now (other node types is wrapping into a single term implicit group when multiplier is applied)
- Renamed
nonEmpty
Group's property to disallowEmpty
- Added optimisation for syntax tree by dropping redundant root
Group
when it contains a single Group
term (return this Group
as a result)
- Changed lexer's match functionality
- Changed
Lexer#matchProperty()
and Lexer#matchType()
to return an object instead of match tree. A match tree stores in matched
field when AST is matched to grammar successfully, otherwise an error in error
field. The result object also has some methods to test AST node against a match tree: getTrace()
, isType()
, isProperty()
and isKeyword()
- Added
Lexer#matchDeclaration()
method
- Removed
Lexer#lastMatchError
(error stores in match result object in error
field)
- Added initial implementation of search for AST segments (new lexer methods:
Lexer#findValueSegments()
, Lexer#findDeclarationValueSegments()
and Lexer#findAllSegments
)
- Implemented
SyntaxReferenceError
for unknown property and type references
- Renamed field in resulting object of
property()
function: variable
→ custom
- Fixed issue with readonly properties (e.g.
line
and column
) of Error
and exception on attempt to write in iOS Safari