Page
Library
Module
Module type
Parameter
Class
Class type
Source
tw is an OCaml implementation of Tailwind CSS v4. You assemble utilities as ordinary OCaml values and compile them to CSS through the same typed variable-and-layer pipeline Tailwind uses, producing byte-for-byte identical output. Unknown utilities are caught at compile time, and nothing depends on Node.js, PostCSS, or the Tailwind CLI at run time.
open Tw
(* A set of utilities is a value of type [Tw.t list]. *)
let card =
[
flex; flex_col; gap 4; p 6;
bg white; rounded_lg; shadow_sm;
border; border_color ~shade:200 gray;
hover [ shadow_md ];
dark [ bg ~shade:800 gray; text ~shade:100 gray ];
]@tailwindcss/typography (prose) and @tailwindcss/forms are fully implemented.Tw.str "flex p-4 bg-blue-500" turns class strings into typed utilities for dynamic class lists.Requires OCaml >= 5.2.
opam install twopen Tw
(* Spacing scales: the integer is multiplied by 0.25rem, so [p 4] is 1rem. *)
let layout = [ flex; items_center; gap 4; p 6; mx_auto; max_w_4xl ]
(* Colors default to shade 500; [~shade] picks another, [~opacity] adds alpha. *)
let colors = [ bg blue; text white; border_color ~shade:300 gray; bg ~opacity:50 white ]
(* Variants nest as functions: responsive breakpoints, state, and dark mode. *)
let responsive =
[ p 4; md [ p 8 ]; lg [ p 12 ]; bg blue; hover [ bg ~shade:600 blue ]; dark [ text ~shade:300 gray ] ]
(* The typography plugin, including per-element variants. *)
let article =
[ prose; prose_lg; mx_auto; prose_headings [ text ~shade:600 blue ]; prose_code [ bg ~shade:100 gray ] ]open Tw
(* [to_classes] returns the value for an HTML [class] attribute. *)
let class_attr = to_classes [ flex; p 4; bg blue ]
(* [to_css] builds a stylesheet; [Css.to_string] renders it to text. *)
let stylesheet = to_css [ flex; p 4; bg blue; hover [ bg ~shade:600 blue ] ]
let css = Css.to_string ~minify:true stylesheet(* [Tw.str] parses a class string into utilities (raises on unknown classes). *)
let styles = Tw.str "flex items-center gap-4 p-6 bg-white rounded-lg shadow-sm"
(* [Tw.of_string] parses a single class and returns a result. *)
let parsed = Tw.of_string "hover:bg-blue-600" (* Ok _ *)
let rejected = Tw.of_string "not-a-class" (* Error (`Msg _) *)# Generate CSS for specific classes
tw -s "flex p-4 bg-blue-500 hover:bg-blue-600"
# Scan files for classes
tw src/ > styles.css
# Compare with real Tailwind CSS
tw -s "prose mb-4 dark:text-gray-300" --diffAll Tailwind CSS v4 core utilities and both official plugins:
Category | Examples |
|---|---|
Layout |
|
Spacing |
|
Sizing |
|
Typography |
|
Colors |
|
Opacity |
|
Borders |
|
Effects |
|
Transforms |
|
Transitions |
|
Interactivity |
|
Filters |
|
Tables |
|
Prose |
|
Forms |
|
Variant | Example |
|---|---|
Responsive |
|
State |
|
Dark mode |
|
Group/Peer |
|
Pseudo-elements |
|
Prose elements |
|
Stacked |
|
The --diff and --tailwind CLI modes require the tailwindcss standalone binary for comparison testing:
# macOS (Apple Silicon)
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-arm64
chmod +x tailwindcss-macos-arm64
sudo mv tailwindcss-macos-arm64 /usr/local/bin/tailwindcss
# Linux (x64)
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64
chmod +x tailwindcss-linux-x64
sudo mv tailwindcss-linux-x64 /usr/local/bin/tailwindcssdune build # build the library and CLI
dune runtest # run all tests, including README examples
# Compare a single utility with Tailwind
dune exec -- tw -s "bg-blue-500 hover:bg-blue-600" --diffISC — see LICENSE.md.