Skip to content

v0.1.0, pre-release

Style without
the noise.

An expressive utility-first CSS framework. Designed for clarity. Built for speed.

81
utilities
12
variants
10
packages
0
bytes of runtime in your app

01Live compiler

Type here. It compiles in this tab.

This is the real compiler, running in your browser. Change a class and watch the stylesheet rewrite itself.

You write
You get
It ships11 rules
:root {
  --croff-color-brand: #c8fd12;
  --croff-color-dark: #0a0a0a;
  --croff-color-light: #f5f2f1;
  --croff-spacing-2: 0.5rem;
  --croff-spacing-3: 0.75rem;
  --croff-spacing-5: 1.25rem;
  --croff-radius-sm: 0.25rem;
  --croff-text-weight-semibold: 600;
  --croff-duration-normal: 200ms;
}

.flex\(row\) {
  display: flex;
  flex-direction: row;
}

.align\(center\) {
  align-items: center;
}

.gap\(2\) {
  gap: var(--croff-spacing-2);
}

.padding\(3\,5\) {
  padding: var(--croff-spacing-3) var(--croff-spacing-5);
}

.text-weight\(semibold\) {
  font-weight: var(--croff-text-weight-semibold);
}

.color\(dark\) {
  color: var(--croff-color-dark);
}

.bg\(brand\) {
  background-color: var(--croff-color-brand);
}

.radius\(sm\) {
  border-radius: var(--croff-radius-sm);
}

.transition\(colors\) {
  transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke;
  transition-duration: var(--croff-duration-normal);
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

.hover\:bg\(light\):hover {
  background-color: var(--croff-color-light);
}

.focus-visible\:ring\(2\,light\):focus-visible {
  box-shadow: 0 0 0 2px var(--croff-color-light);
}

02The language

Every part of a class means something.

An expression has a grammar and a real parser. Read one from left to right.

md:hover:bg(alpha(brand,50))

  • md:BreakpointComes from your theme, and wraps the rule in a media query.
  • hover:StateAdds a pseudo-class. Stack as many variants as you need.
  • bgUtilityLooked up in the registry. A typo is an error, with a suggestion.
  • (alpha(brand,50))Checked valuebrand has to be a color in your theme, and 50 a percentage from 0 to 100.
Generated by the real compiler
:root {
  --croff-color-brand: #c8fd12;
}

@media (min-width: 768px) {
  .md\:hover\:bg\(alpha\(brand\,50\)\):hover {
    background-color: color-mix(in srgb, var(--croff-color-brand) 50%, transparent);
  }
}

03Why CROFF

A styling language, with a compiler behind it.

0

Zero runtime styling

Everything happens at build time. Your users download a stylesheet and nothing else, because no CROFF code runs in the browser.

flex(row) gap(4) md:width(1/2)

Expressive syntax

Utilities read like small function calls. A real parser reads them, not a pile of string splits.

Deterministic CSS

The output is a function of the set of expressions in your source. The same source produces the same bytes, in any scan order.

Design tokens first

Colors, spacing and type are tokens, compiled to custom properties. Only the tokens you use reach production.

Extensible by design

Utilities and variants are data in a registry. A plugin adds its own through the same path as the built-ins.

Framework independent

CROFF reads text and writes CSS. No markup is rewritten, so anything that renders a class attribute works.

.html.jsx.tsx.vue.svelte.astro.mdx

04Input and output

What you read is what you debug.

Each expression becomes one rule whose selector is that expression. Nothing in your markup is rewritten, so the class you see in DevTools is the class you wrote.

What you write
<div class="
  flex(col) md:flex(row)
  gap(4) padding(6)
  bg[#121212] radius(lg)
  width[calc(100%-2rem)]
">
  <h2 class="text-size(xl) hover:color(brand)">
    Hello CROFF
  </h2>
</div>
What ships, generated by the real compiler
:root {
  --croff-color-brand: #c8fd12;
  --croff-spacing-4: 1rem;
  --croff-spacing-6: 1.5rem;
  --croff-radius-lg: 0.75rem;
  --croff-text-size-xl: 1.25rem;
}

.flex\(col\) {
  display: flex;
  flex-direction: column;
}

.gap\(4\) {
  gap: var(--croff-spacing-4);
}

.width\[calc\(100\%-2rem\)\] {
  width: calc(100% - 2rem);
}

.padding\(6\) {
  padding: var(--croff-spacing-6);
}

.text-size\(xl\) {
  font-size: var(--croff-text-size-xl);
}

.bg\[\#121212\] {
  background: #121212;
}

.radius\(lg\) {
  border-radius: var(--croff-radius-lg);
}

.hover\:color\(brand\):hover {
  color: var(--croff-color-brand);
}

@media (min-width: 768px) {
  .md\:flex\(row\) {
    display: flex;
    flex-direction: row;
  }
}

05In version 0.1.0

Rules you can rely on.

Parentheses are checked. Brackets are raw.

gap(4) must be a token. gap[1.5rem] is an explicit escape hatch to raw CSS. A reviewer can spot every off-system value at a glance.

expressions
bg(brand)
bg(alpha(brand,50))
width[calc(100%-var(--sidebar-width))]
md:hover:transform(translate-y(-2px),scale(1.02))

Mistakes are errors, with a way forward.

croff check reports unknown utilities, invalid values, whitespace inside expressions and class names built at runtime, each with its file and position.

croff check
src/card.tsx:12:18: error unknown-utility: Unknown utility "pad".
  hint: Did you mean "padding"?
src/card.tsx:14:9: error invalid-argument: "brnad" is not a valid value for "bg". Expected colors token; transparent, current, inherit; var(--name); alpha(color,0–100).
  hint: Did you mean "brand"?

06Installation

Add it to a Vite project in three steps.

  1. 1
    Install
    pnpm add -D @croff/core @croff/vite
  2. 2
    vite.config.ts
    import croff from "@croff/vite";
    
    export default {
      plugins: [croff()],
    };
  3. 3
    src/croff.css
    @croff reset;
    @croff;

Version 0.1.0 is a pre-release and isn't on a package registry yet. Until it is, the installation guide explains how to build and link it from source.

07Ecosystem

Small packages, each with one job.

  1. 01Your sourceAny text file
  2. 02ScannerFinds expressions
  3. 03ParserReads the grammar
  4. 04RegistryChecks against your theme
  5. 05CompilerOrders and prints
  6. 06CSSOnly what you used
  • @croff/corePublic API, configuration and project orchestration
  • @croff/parserTokenizer, parser and AST for the utility language
  • @croff/compilerDeterministic CSS generation and source maps
  • @croff/themeDesign tokens and CSS variable generation
  • @croff/registryUtility and variant definitions
  • @croff/scannerSource scanning and file watching
  • @croff/clicroff init, dev, build and check
  • @croff/viteVite plugin with hot updates
  • @croff/postcssPostCSS plugin
  • @croff/plugin-apiAdd utilities, variants and tokens