Core Concepts
Utility language
The syntax of a CROFF expression.
Shape of an expression
md:hover:bg(brand-dark)An expression is zero or more variants, each followed by a colon, then a utility name, then a value.
Grammar
expression = { variant ":" } utility
utility = name ( call | bracket )
call = "(" [ argument { "," argument } ] ")"
argument = function | word
function = name call
bracket = "[" raw-css "]"The full grammar, with the character classes and every rule below in detail, is in docs/grammar.md in the repository.
Call form
Arguments in parentheses are validated.
<div class="padding(4,8) bg(alpha(brand,50)) width(1/2)"></div>:root {
--croff-color-brand: #c8fd12;
--croff-spacing-4: 1rem;
--croff-spacing-8: 2rem;
}
.width\(1\/2\) {
width: 50%;
}
.padding\(4\,8\) {
padding: var(--croff-spacing-4) var(--croff-spacing-8);
}
.bg\(alpha\(brand\,50\)\) {
background-color: color-mix(in srgb, var(--croff-color-brand) 50%, transparent);
}Empty parentheses are valid where every argument is optional: flex(), border().
Nested functions
An argument can be a function, nested to any depth up to 16. What's allowed depends on the utility.
| Function | Used by | Meaning |
|---|---|---|
alpha(color,percent) | Color utilities | A color at an opacity. |
var(--name), var(--name,fallback) | Most value utilities | A custom property of your own. |
rotate(...), translate-y(...), scale(...) as a factor, and others | transform | A transform function. |
Bracket form
Anything in brackets is raw CSS. See Arbitrary values.
No whitespace
An expression can't contain whitespace, because browsers split class on whitespace.
width[calc(100% - 1px)] Error: whitespace
width[calc(100%-1px)] OK: CROFF inserts the spaces calc() needs
margin[0_auto] OK: an underscore is a spaceEscaping
In call arguments, a backslash makes the next character literal: \, \( \) \:. In brackets, \_ is a literal underscore and \[ \] \( \) don't count as nesting. Other backslash sequences pass through to CSS, so content['\201C'] works.
You never write CSS escapes for the class name itself. The compiler handles that.
Naming
Utilities are lowercase and hyphenated, and spell out what they do: padding-x, min-width, border-color. Aliases are avoided. The two deliberate shortcuts are color, for text-color, and scale, for a scaling transform.
Bare words are not utilities
A word with no value, like flex or card, is an ordinary class that CROFF ignores. That's why group works as a marker for group-hover, and why CROFF can't conflict with your classes.
