A type-safe CSS-in-TypeScript library for Deno with scoped styles, theming, and a complete CSS at-rule system.
This project was vibe coded with Claude.
- Scoped class name generation with content-based hashing
- Full CSS at-rule support (@font-face, @property, @page, @counter-style, @color-profile)
- CSS variable contracts with type-safe theming
- Nested selectors and pseudo-classes
- Style composition with
use() - Zero runtime in production (all CSS is generated at build time)
deno add jsr:@baetheus/cssimport { render, style } from "@baetheus/css";
const button = style({
backgroundColor: "blue",
color: "white",
padding: "8px 16px",
borderRadius: "4px",
});
// Use in DOM
element.className = button.toString();
// Render CSS
const css = render(button);import { render, style } from "@baetheus/css";
const card = style({
padding: "16px",
transition: "transform 0.2s",
select: {
"&:hover": { transform: "scale(1.02)" },
"& > h2": { marginTop: "0" },
"@media (min-width: 768px)": { padding: "24px" },
},
});
console.log(render(card));import { render, style } from "@baetheus/css";
// Style an HTML element directly
const body = style("body", { margin: "0", fontFamily: "sans-serif" });
// Style by ID
const header = style("#header", { position: "fixed", top: "0" });
console.log(render(body, header));import { contract, render, style, vars } from "@baetheus/css";
// Define the contract with arbitrary nesting (null marks each variable)
const theme = contract({
colors: {
primary: null,
secondary: null,
brand: { light: null, dark: null },
},
spacing: null,
});
// Use var references in styles
const card = style({
color: theme.colors.primary,
backgroundColor: theme.colors.brand.light,
padding: theme.spacing,
});
// Create theme implementations
const lightTheme = vars(theme, {
colors: {
primary: "blue",
secondary: "green",
brand: { light: "#eef", dark: "#335" },
},
spacing: "8px",
});
const darkTheme = vars(theme, {
colors: {
primary: "white",
secondary: "#ccc",
brand: { light: "#335", dark: "#eef" },
},
spacing: "8px",
});
// Apply theme
document.body.className = lightTheme.toString();
console.log(render(lightTheme, card));import { render, style, use } from "@baetheus/css";
const base = style({ padding: "8px" });
const primary = style({ backgroundColor: "blue", color: "white" });
const large = style({ fontSize: "1.25rem" });
// Combine into a single class string
const className = use(base, primary, large);
// ".abc123 .def456 .ghi789"import { at, render } from "@baetheus/css";
// @font-face
const roboto = at("@font-face", {
fontFamily: "Roboto",
src: "url('/fonts/roboto.woff2') format('woff2')",
fontWeight: "400",
fontDisplay: "swap",
});
// @property (CSS Houdini)
const themeColor = at("@property --theme-color", {
syntax: '"<color>"',
inherits: "true",
initialValue: "blue",
});
// @counter-style
const thumbs = at("@counter-style thumbs", {
system: "cyclic",
symbols: "๐",
suffix: " ",
});
// @page
const firstPage = at("@page :first", {
marginTop: "2in",
});
console.log(render(roboto, themeColor, thumbs, firstPage));import {
MINIMAL_RENDER_OPTIONS,
render,
STANDARD_RENDER_OPTIONS,
style,
} from "@baetheus/css";
const button = style({ color: "blue" });
// Human-readable output (default)
console.log(render(button));
console.log(render(STANDARD_RENDER_OPTIONS, button));
// Minified output
console.log(render(MINIMAL_RENDER_OPTIONS, button));import { properties, style } from "@baetheus/css";
// Define reusable style properties with type checking
const flexCenter = properties({
display: "flex",
alignItems: "center",
justifyContent: "center",
});
const card = style({
...flexCenter,
padding: "16px",
});style(input)- Creates a Style with auto-generated class namestyle(selector, input)- Creates a Style with a custom selectorrender(...styles)- Renders styles to CSS stringrender(options, ...styles)- Renders with custom formatting optionsuse(...styles)- Combines multiple styles into a class name stringproperties(input)- Identity function for type-checked style objectsisStyle(value)- Type guard for Style objects
contract(shape)- Creates a type-safe CSS variable contractvars(contract, values)- Creates a theme implementation from a contract
at(rule, properties)- Creates styles for unnestable at-rules
STANDARD_RENDER_OPTIONS- Pretty-printed CSS with newlines and indentationMINIMAL_RENDER_OPTIONS- Minified CSS with no whitespace
- vanilla-extract - The primary inspiration
for the API design, particularly the
style,contract, and theming patterns - Sass - Influence on nesting and selector composition
- fp-ts - Functional programming patterns and type-safe design
Contributions are welcome! This is an experimental project that was vibe coded, so there's plenty of room for improvement.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Run tests
deno test
# Type check
deno check mod.ts
# Format
deno fmtMIT License - see LICENSE for details.