tinycss2

Low-level CSS Syntax Level 3 parser and generator for Python

Library
PyPI
v1.5.1
190stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
53/100Fair
Development Activity32
Maintenance28
Community72
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture82
Code Quality80
Innovation70
Learning Curve75

tinycss2 is a low-level CSS parser and serializer for Python that implements the CSS Syntax Level 3 specification. It tokenizes and parses CSS text into a tree of token/rule objects and can generate CSS text back from those objects, but deliberately stops at the syntax layer: it knows the grammar of CSS (rules, blocks, declarations, at-rules) without knowing the semantics of any specific property or module, leaving that interpretation to the caller.

Maintained by Kozea and supported by CourtBouillon, tinycss2 is the CSS tokenizer/parser underneath WeasyPrint (the HTML-to-PDF renderer) and other tools that need standards-compliant, low-level CSS parsing without pulling in a full browser engine. Its only runtime dependency is webencodings, keeping it lightweight enough to embed in document-processing and static-site pipelines.

What You Get

  • A CSS tokenizer that turns raw CSS text into a stream of syntax tokens per the CSS Syntax Level 3 spec
  • Parsers for stylesheets, rule lists, declaration lists, and individual component values
  • A serializer that turns the parsed AST back into valid CSS text
  • Color parsing modules covering CSS Color 3, 4, and 5 syntaxes (color3.py, color4.py, color5.py)
  • An nth.py helper for parsing :nth-child()-style An+B expressions

Common Use Cases

  • Building document-rendering pipelines (as WeasyPrint does) that need standards-compliant CSS parsing without a full browser engine
  • Writing CSS preprocessors, linters, or minifiers that operate on a syntax-level AST rather than regex-matching CSS text
  • Extracting or rewriting specific CSS constructs (colors, selectors, at-rules) programmatically in build tooling
  • Parsing embedded or user-supplied CSS safely in applications that sanitize or transform stylesheets before use

Under The Hood

Architecture: The library is split cleanly along the CSS Syntax Level 3 spec’s own phases: tokenizer.py implements the low-level tokenizer, parser.py builds on it to parse stylesheets/rule-lists/declarations into an AST defined in ast.py, and serializer.py reverses the process back to CSS text. Separate color3.py/color4.py/color5.py modules layer optional color-value parsing on top without coupling it to the core tokenizer, and nth.py provides a focused parser for An+B micro-syntax used in selectors.

Tech Stack: Pure Python 3.10+, built with the flit_core build backend, with a single runtime dependency (webencodings) for correct CSS byte-to-text decoding per the spec’s encoding-detection rules.

Code Quality: The tests/ directory exercises the tokenizer, parser, serializer, and each color-syntax module against spec-derived cases; the project has a documented code of conduct and is professionally maintained by CourtBouillon, with a public changelog tracked via GitHub releases. Commit activity is modest but steady, consistent with a stable, spec-scoped library that doesn’t need frequent breaking changes.

API Design: The public API exposes a small number of top-level functions (parse_stylesheet, parse_declaration_list, parse_component_value_list, serialize) that map directly onto CSS Syntax Level 3 spec productions, so anyone familiar with the spec can predict the API shape; because it stays at the syntax level, callers must bring their own knowledge of which properties/values are valid, which is a deliberate trade-off rather than an oversight.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search