Tailwind OCaml#
Type-safe Tailwind CSS generation for OCaml with a revolutionary GADT-based interface for succinct, compile-time validated styling.
This project provides two main libraries:
tailwind: Core library for type-safe Tailwind CSS class generationtailwind-html: High-level HTML component library with GADT-based heterogeneous list interface built on Htmlit
Features#
- GADT-based Interface: Succinct heterogeneous list syntax with compile-time type safety
- Zero Runtime Cost: All CSS generation happens at compile time
- Comprehensive Grid Support: Full CSS Grid integration with type-safe properties
- Type-Safe Colors & Spacing: Exhaustive variants with compile-time validation
- Built-in Components: Pre-styled buttons, cards, and layout helpers
Complete Tailwind Coverage#
- Typography: Font sizes, weights, text alignment with type-safe variants
- Layout: CSS Grid, Flexbox, spacing with compile-time validation
- Colors: Full palette (gray, blue, red, green, etc.) with variant checking
- Effects: Shadows, borders, rounded corners, transitions
- Components: Pre-built buttons, cards, and layout helpers
- Type Safety: GADT-based heterogeneous lists prevent invalid combinations
Quick Start#
GADT Interface (Recommended)#
The new GADT-based interface provides succinct, type-safe styling with heterogeneous lists:
open Htmlit
open Tailwind_html
(* Create a centered card with CSS Grid *)
let create_hero_section () =
div ~styles:[
grid;
grid_cols 1;
gap (rem 2.0);
padding (rem 3.0);
text_center;
] [
h1 ~styles:[
font_size `Xl3;
font_weight `Bold;
text_color (blue 600);
margin_bottom (rem 1.5);
] [txt "Welcome to Tailwind OCaml"];
p ~styles:[
font_size `Lg;
text_color (gray 600);
margin_bottom (rem 2.0);
] [txt "Type-safe CSS with compile-time guarantees"];
(* Built-in button components *)
btn_primary ~size:`Lg [txt "Get Started"];
]
CSS Grid Layouts#
(* Three-column responsive grid *)
div ~styles:[
grid;
grid_cols 3;
gap (rem 1.5);
] [
card [h3 [txt "Feature 1"]; p [txt "Description"]];
card [h3 [txt "Feature 2"]; p [txt "Description"]];
card [h3 [txt "Feature 3"]; p [txt "Description"]];
]
Built-in Components#
(* Pre-styled components with size variants *)
btn_primary ~size:`Lg [txt "Primary Action"];
btn_secondary [txt "Secondary Action"];
btn_outline ~size:`Sm [txt "Outline Button"];
(* Layout helpers *)
container [
card [
h2 ~styles:[font_size `Xl; margin_bottom (rem 1.0)] [txt "Card Title"];
p ~styles:[text_color (gray 600)] [txt "Card content with automatic styling"];
];
]
Examples#
The examples/ directory showcases the GADT interface across various use cases:
Available Examples#
# Build all examples
dune build examples/
# Hello World with GADT interface
dune exec examples/hello_tailwind_01.exe > hello.html
# Colors and Typography showcase
dune exec examples/colors_and_typography_02.exe > colors.html
# CSS Grid and Layout demonstrations
dune exec examples/layout_and_spacing_03.exe > layout.html
# Responsive design patterns
dune exec examples/responsive_design_04.exe > responsive.html
# Visual effects and styling
dune exec examples/effects_and_variants_05.exe > effects.html
# Component patterns and reusable elements
dune exec examples/patterns_and_components_06.exe > patterns.html
# Complete application showcase
dune exec examples/comprehensive_showcase_07.exe > showcase.html
# Button component demonstration
dune exec examples/button_demo.exe > buttons.html
# Generate index page linking all examples
dune exec examples/index_html_generator.exe > index.html
Example Highlights#
CSS Grid Layout (layout_and_spacing_03.ml):
(* Three-column grid with gap variations *)
div ~styles:[
grid;
grid_cols 3;
gap (rem 1.0);
] [
div ~styles:[bg_color (blue 100); padding (rem 1.0)] [txt "Item 1"];
div ~styles:[bg_color (green 100); padding (rem 1.0)] [txt "Item 2"];
div ~styles:[bg_color (purple 100); padding (rem 1.0)] [txt "Item 3"];
]
(* Asymmetric grid gaps *)
div ~styles:[
grid;
grid_cols 2;
gap_x (rem 2.0);
gap_y (rem 0.5);
] (List.init 4 (fun i ->
div ~styles:[bg_color (purple 200); text_center] [
txt (Printf.sprintf "Box %d" (i + 1))
]
))
Built-in Components (button_demo.ml):
(* Size variants with consistent styling *)
div ~styles:[flex; flex_col; gap (rem 1.0)] [
btn_primary ~size:`Sm [txt "Small Primary"];
btn_primary [txt "Default Primary"];
btn_primary ~size:`Lg [txt "Large Primary"];
btn_secondary [txt "Secondary Button"];
btn_outline [txt "Outline Button"];
]
Responsive Cards (comprehensive_showcase_07.ml):
section ~styles:[margin_bottom (rem 4.0)] [
h3 ~styles:[font_size `Xl2; text_center; margin_bottom (rem 3.0)] [
txt "Features"
];
div ~styles:[grid; grid_cols 1; gap (rem 2.0)] [
card [
h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (blue 600)] [
txt "🎯 Type Safety"
];
p ~styles:[text_color (gray 600)] [
txt "Catch styling errors at compile time with GADT-based type checking."
];
];
card [
h4 ~styles:[font_size `Xl; font_weight `Semibold; text_color (green 600)] [
txt "⚡ Performance"
];
p ~styles:[text_color (gray 600)] [
txt "Zero runtime overhead with compile-time CSS generation."
];
];
];
]
Tailwind v4 Support#
This library supports Tailwind v4's CSS-first approach:
/* Generated input.css - no config file needed! */
@import "tailwindcss";
@theme {
--font-sans: 'Inter', system-ui, sans-serif;
--color-brand-600: #2563eb;
/* Custom theme extensions */
}
To process the CSS:
npx tailwindcss@next -i input.css -o output.css
API Reference#
Tailwind_html (GADT Interface)#
The high-level GADT interface provides succinct, type-safe styling with heterogeneous lists:
Layout Properties#
~styles:[
(* Display *)
grid | flex | block | inline | hidden;
(* Grid System *)
grid_cols 3 | grid_rows 2;
gap (rem 1.0) | gap_x (rem 1.5) | gap_y (rem 0.5);
(* Flexbox *)
flex_col | flex_row;
justify_center | justify_between | justify_end;
items_center | items_start | items_end;
(* Sizing *)
width full | height screen;
min_height screen | max_width (rem 64.0);
]
Typography Properties#
~styles:[
(* Font Sizes *)
font_size `Xs | font_size `Sm | font_size `Base | font_size `Lg;
font_size `Xl | font_size `Xl2 | font_size `Xl3;
(* Font Weights *)
font_weight `Light | font_weight `Normal | font_weight `Medium;
font_weight `Semibold | font_weight `Bold;
(* Text Styling *)
text_center | text_left | text_right;
text_color (blue 600) | text_color (gray 500);
]
Color System#
~styles:[
(* Background Colors *)
bg_color (blue 50) | bg_color (gray 100) | bg_color (red 500);
bg_color (Tailwind.Color.white) | bg_color (green 600);
(* Text Colors *)
text_color (gray 800) | text_color (blue 600) | text_color (red 500);
(* Border Colors *)
border_color (gray 200) | border_color (blue 300);
]
Spacing Properties#
~styles:[
(* Padding *)
padding (rem 1.0) | padding_x (rem 1.5) | padding_y (rem 2.0);
(* Margin *)
margin (rem 1.0) | margin_x auto | margin_bottom (rem 2.0);
margin_top (rem 1.5) | margin_left (rem 0.5);
]
Visual Effects#
~styles:[
(* Shadows *)
shadow `Sm | shadow `Md | shadow `Lg | shadow `Xl;
(* Borders *)
border | rounded `Sm | rounded `Md | rounded `Lg | rounded `Full;
(* Transitions *)
transition;
]
Built-in Components#
(* Button Components *)
btn_primary ~size:`Lg [txt "Primary Button"];
btn_secondary ~size:`Sm [txt "Secondary Button"];
btn_outline [txt "Outline Button"];
(* Layout Components *)
container [content]; (* Max-width container with auto margins *)
card [content]; (* Pre-styled card with padding and shadow *)
(* HTML Elements with Styling *)
h1 ~styles:[font_size `Xl3; font_weight `Bold] [txt "Heading"];
p ~styles:[text_color (gray 600); margin_bottom (rem 1.0)] [txt "Paragraph"];
div ~styles:[grid; grid_cols 2; gap (rem 1.0)] [content];
section ~styles:[margin_bottom (rem 2.0)] [content];
Low-Level Tailwind Module#
For advanced use cases, the core Tailwind module provides detailed control:
open Tailwind
let classes = Css.tw [
Display.grid;
Grid.(to_class (template_cols (`Cols 3)));
Spacing.(to_class (gap `All (Size.rem 1.0)));
Color.bg (Color.make `Blue ~variant:`V50 ());
]
let html_class = to_string classes (* "grid grid-cols-3 gap-4 bg-blue-50" *)
Getting Started#
Add to your dune-project:
(package
(name myproject)
(depends
ocaml
dune
tailwind
tailwind-html
htmlit))
Then in your OCaml code:
open Htmlit
open Tailwind_html
let my_page = El.html [
El.head [El.title [txt "My App"]];
El.body ~at:[classes_attr [min_height screen; bg_color (gray 50)]] [
container [
h1 ~styles:[font_size `Xl3; text_center; margin_bottom (rem 2.0)] [
txt "Welcome to Type-Safe CSS!"
];
btn_primary [txt "Get Started"];
];
];
]
Testing#
Run the test suite:
dune test
Contributing#
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
License#
MIT License - see LICENSE file for details
Acknowledgments#
- Built on top of Htmlit by Daniel Bünzli
- Inspired by Tailwind CSS