CSS tooling for OCaml -- a typed AST, parser, pretty-printer, and optimizer for modern CSS.
Most CSS toolchains target JavaScript runtimes. Cascade provides the same core capabilities -- parsing, rendering, and structural comparison -- as a native OCaml library with zero runtime dependencies beyond the stdlib. Properties, values, and selectors are represented as OCaml types rather than strings, so invalid constructs are caught at compile time.
Cascade targets CSS Level 3 and Level 4 modules. The parser handles the full syntax defined in CSS Syntax Level 3 and the printer produces spec-conformant output with optional minification.
| Specification | Coverage |
|---|---|
| Selectors Level 4 | Class, ID, element, universal, attribute, pseudo-classes (:hover, :nth-child(), :where(), :not(), :is(), :has()), pseudo-elements, combinators, & nesting |
| Values and Units Level 4 | ~30 length units, calc(), clamp(), min(), max(), minmax(), angles, durations |
| Color Level 4 | Hex, rgb(), hsl(), hwb(), oklch(), oklab(), color-mix(), 148 named colors, 15 color spaces |
| Conditional Rules Level 3 | @media feature queries, @supports property and selector checks |
| Cascade Level 5 | @layer declarations and blocks, CSS-wide keywords |
| Nesting Module | Nested rules with &, nested @media and @supports |
| Container Queries Level 1 | @container with size queries |
| Custom Properties Level 1 | var() with typed fallbacks, @property registration |
| Fonts Level 4 | @font-face descriptors |
| Animations Level 1 | @keyframes, @starting-style |
Over 100 typed CSS properties cover box model, flexbox, grid, logical properties, typography, borders, backgrounds, gradients, transforms, transitions, animations, filters, and vendor-prefixed properties.
opam install cascadeopen Cascade.Css
let button =
rule ~selector:(Selector.class_ "btn")
[ display Inline_block
; background_color (hex "#3b82f6")
; color (hex "#ffffff")
; padding [ Rem 0.5 ]
; border_radius (Rem 0.375)
]
let () = print_string (to_string (v [ button ]))Output:
.btn {
display: inline-block;
background-color: #3b82f6;
color: #fff;
padding: 0.5rem;
border-radius: 0.375rem;
}cascade [--minify] [--optimize] [--pretty] [FILE]
Reads a CSS file (or stdin with -) and outputs formatted CSS. The
--optimize flag merges duplicate rules and removes redundant declarations.
cascade style.css # pretty-print
cascade --minify style.css # minify
cascade --optimize --minify style.css # optimize and minify
cat style.css | cascade --minify - # read from stdincssdiff [--color=WHEN] [--diff=MODE] FILE1 FILE2
Compares two CSS files using structural parsing, detecting added, removed,
and modified rules, property value changes, and reordered rules. Three diff
modes are available: auto (default -- uses tree diff for structural changes,
string diff otherwise), tree (force structural comparison), and string
(character-level comparison).
cssdiff reference.css output.css
cssdiff --diff=tree reference.css output.css
NO_COLOR=1 cssdiff reference.css output.csscascade-- typed CSS AST, parser, pretty-printer, and optimizer. The main module isCascade.Css.cascade.tools-- structural CSS comparison (Css_tools.Css_compare,Css_tools.Tree_diff,Css_tools.String_diff).
- CSS nesting is parsed and printed but the optimizer does not flatten nested rules. A round-trip through the parser preserves nesting structure.
- The parser uses error recovery for declarations but does not yet implement the full error recovery algorithm from CSS Syntax Level 3 section 9.
@importrules are preserved as-is; Cascade does not resolve or inline imported stylesheets.- No source-map support.