Vanilla / HTML integration
For plain HTML pages, prototypes, internal tools, or any project without a build pipeline. Two stylesheet imports, then use Caster class names. This is exactly how the USA Clean prototype consumes Caster.
1 · Get the files
Two options. Pick one.
Option A — Vendor into your project (recommended for production)
Copy the two files into your project. They're stable enough to vendor; updates are infrequent.
your-project/
├── css/
│ ├── caster-tokens.css # copy of design-system/tokens/tokens.css
│ └── caster-components.css # copy of design-system/components/components.css
└── index.htmlOption B — Load from the deployed showcase (prototypes only)
Quick & dirty for sandboxes. Don't ship to real users this way — the showcase isn't a CDN, and it can't guarantee uptime.
<link rel="stylesheet" href="https://demo.thecxlabs.com/design-system/tokens/tokens.css?v=0.16.3">
<link rel="stylesheet" href="https://demo.thecxlabs.com/design-system/components/components.css?v=0.16.3">2 · Import order matters
Caster uses Open Sans. Tokens reference the font family, so the font import has to come before tokens.
<!-- 1. Open Sans (Caster's only typeface) -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700;800&display=swap">
<!-- 2. Caster tokens — defines all --caster-* CSS custom properties -->
<link rel="stylesheet" href="css/caster-tokens.css">
<!-- 3. Caster components — defines .btn, .pill, .product-card etc. -->
<link rel="stylesheet" href="css/caster-components.css">
<!-- 4. Your own CSS (overrides Caster as needed) -->
<link rel="stylesheet" href="css/site.css">3 · Use the components
Reference the showcase pages for full markup. Quick examples:
Button
<button class="btn btn-primary">Add to cart</button>
<button class="btn btn-brand">Save changes</button>
<button class="btn btn-outline">Cancel</button>Pill
<span class="pill pill-brand">OEM</span>
<span class="pill pill-success">In stock · 47 units</span>
<span class="pill pill-accent">↺ Subscribe & Save 10%</span>4 · Theming via CSS variables
Caster components read --caster-* custom properties. Override at any scope to retheme — globally on :root, or scoped to a specific element.
Global override
<!-- In your site.css, after caster-components.css -->
<style>
:root {
/* Make all brand-colored buttons green instead of blue */
--caster-color-brand-default: #1a8a3f;
--caster-color-brand-hover: #0d6f2a;
}
</style>Scoped override
Useful for "this section uses a different palette" — promo zones, holiday banners, white-label pages.
<section style="--caster-color-brand-default: #1a8a3f;
--caster-color-brand-hover: #0d6f2a;">
<!-- Caster components inside this section see the green brand color -->
<button class="btn btn-brand">Now green</button>
</section>5 · Using tokens in your own CSS
If you're writing custom components alongside Caster, reference the same token system to stay consistent.
<!-- In your site.css -->
<style>
.my-promo-banner {
background: var(--caster-color-brand-deep);
color: var(--caster-color-text-inverted);
padding: var(--caster-spacing-4) var(--caster-spacing-6);
border-radius: var(--caster-radius-card);
font-family: var(--caster-font-family-sans);
font-weight: var(--caster-font-weight-semibold);
font-size: var(--caster-font-size-sm);
}
</style>--caster-color-brand-default, not --caster-color-blue-700. The semantic layer is the contract — primitives can shift between versions.
6 · Responsive considerations
Caster components are mobile-first by default. Three breakpoints:
| Range | Token | Min width |
|---|---|---|
| Mobile / Small | --caster-breakpoint-small | 0 (default) |
| Tablet / Medium | --caster-breakpoint-medium | 768px |
| Desktop / Large | --caster-breakpoint-large | 1200px |
CSS variables can't drive media queries directly, so write breakpoints with literal values matched to the tokens:
<style>
.my-grid {
display: grid;
grid-template-columns: 1fr; /* mobile default */
}
@media (min-width: 768px) {
.my-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1200px) {
.my-grid { grid-template-columns: repeat(4, 1fr); }
}
</style>Common pitfalls
"My buttons look unstyled"
Both stylesheets need to load. Open DevTools → Network and confirm both tokens.css and components.css are 200 OK. Then check the order — tokens must come before components, since components reference token variables.
"My font looks wrong"
Open Sans must load. Add the Google Fonts link before the Caster stylesheets. Check DevTools → Network for the font request.
"My existing classes are conflicting with Caster"
Caster uses common class names (.btn, .pill, .product-card). If your project defines these elsewhere, the later import wins. Either rename your existing classes or load Caster first and let your CSS override specifically.
"I changed a primitive but components didn't update"
Source files (tokens/*.json) are inputs. Run npm run build in design-system/build/ to regenerate tokens.css. Or override the semantic token directly in your own CSS and skip the rebuild.