A token can hold a value. This catalog types it
A CSS Variables entry can set --angle: 0deg. It cannot say “this is an <angle>, interpolable, initial 0deg.” Without @property, a gradient-border spin or a token color fade stays discrete or no-ops. The name is defined. The type is not.
A class cannot hold the at-rule. Class bodies wrap as [published-key] .name { … }. @property inside that rule is ignored. A token cannot hold it either — @ and braces are rejected. CSS Properties are the missing catalog: a map of name → syntax, inherits, initial value. Fill it on this widget. Composer and Preview emit the at-rule; publish to send it with the embed.
This page is typed @property, not the token catalog. The Variables page still defines the name. This catalog types that same --name.
When to use it / when not to
| You want | Without typed properties | With this catalog |
|---|---|---|
A token that interpolates under transition or @keyframes on a host that never registered @property | The value jumps, or the animation is a no-op, unless the host already typed the name. | RuleCMS ships @property --angle with the widget. The embed can blend. |
A host that already registered the same --names | Works today. Do not double-register. | Turn published inclusion off. Composer and Preview still use the catalog. |
@theme is one host that already does this — not a requirement. If your site already registers those names, leave inclusion off so RuleCMS does not emit a second @property.This widget's catalog
Open the widget, then CSS Settings, then CSS Properties. This catalog belongs to this widget.
To change the template for the next widget you create, edit the project catalog.
- Preview dumps the catalog as emitted
@propertyblocks — not a:rootlisting and not the token catalog. - Edit is a row of name, syntax, inherits, and initial value. Type
--angle, pick<angle>, set initial0deg— not a pasted@property --angle { … }. Combined syntax strings such as"<color> | <image>"are not accepted; pick*if the value is untyped. Invalid rows are refused. Catalog Save is explicit.
Each entry is one typed custom property:
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}Names must start with -- (same rule as CSS Variables). At most 40 properties; 200 characters per name and per initial value. Initial values reject url(, @, braces, and ;. Any syntax other than * requires a non-empty initial value. When syntax is * and the initial value is empty, initial-value is omitted on emit.
What the renderer does with the catalog
Composer and Preview read this widget's draft catalog. The published embed and the Development (dev.) draft GET read the published widget's catalog. Publish is how a draft catalog goes live.
A new widget starts as a copy of the project catalog. After that, edits here do not write back to the project, and later project edits do not come back here.
| Surface | What happens |
|---|---|
| Composer canvas and Preview | Always inject from this widget's draft catalog when it is non-empty. The published-inclusion flag is ignored here so authors still see the result while they work. |
| Published widget (React SDK and HTML custom element) | The widget fetch includes this widget's catalog when inclusion is on. Nested collections inherit. You do not get a copy per collection. |
When the widget catalog is applied, the renderer emits one <style> of unscoped @property rules. The at-rule is document-global — it is not scoped to the published-key span, and the name is not prefixed. RuleCMS never styles :root or html.
Published widgets
On this widget's CSS Properties page, the Published widgets accordion holds two radios. These radios control whether this widget's published and dev. embed carry the definitions. Composer and Preview still use this widget's catalog when inclusion is off. Changing a radio saves immediately. Catalog Save is separate.
- Include these typed CSS properties when published widgets are rendered. A non-empty catalog is sent with the widget and the renderer registers the types. This is the default.
- My apps already register these @property rules. Do not include them again when the widget is being rendered. Published widgets still carry token names that need those types, but RuleCMS does not ship the
@propertyblocks. Your host stylesheet must register them.
--name the widgets animate. A missing @property on the live page leaves the token discrete.How a published widget receives the catalog
Hosts already fetch the widget once. RuleCMS hangs the catalog on that same response as a sibling of the widget, its collections, CSS variables, class definitions, fonts, keyframes, and themes — not folded into itemList. The field is cssProperties (not a vague properties).
{
"success": true,
"data": {
"widget": { "publishedKey": "…", "itemList": "…", "…": "…" },
"childCollections": { },
"cssProperties": [
{
"name": "--angle",
"syntax": "<angle>",
"inherits": false,
"initialValue": "0deg"
}
]
}
}cssProperties is omitted when the catalog is empty, when inclusion is off, or if the catalog cannot be read. When inclusion is off, the same response also sends includeCssProperties: false so renderers that still receive a list must not emit it. Missing on the payload means include (legacy clients). The widget still loads.
The React renderer (@rulecms/widget-react) and the HTML custom element turn a non-empty catalog into one <style>, for example:
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}Good to know
- This catalog belongs to this widget. Copy and promote copy these columns as-is. The project catalog is only the starting snapshot.
- Same name, last widget wins.
@propertyis document-global. Two embeds that type--angledifferently will race. Use the same registration, or turn inclusion off on the host that already owns the name. RuleCMS does not rename properties per published key. - React and the HTML embed this pass. Other framework SDKs do not emit this catalog yet.
- Leave the catalog empty if the host already registered the same names. Token names on elements still work. Nothing extra is sent to the published page.
Related docs
- CSS Variables — this catalog types a name the Variables page defines
- Class Definitions — the utility bodies that often
transitionoranimatethose names - Fonts — the typeface catalog; another unscoped at-rule
- Keyframes — named
@keyframes; typed properties are what those frames can interpolate - Position try — named
@position-tryfallbacks for overlay classes - Themes — host-dark / color-scheme token overrides
- Cascade layers — wrap class definitions in
@layerso they compete with host Tailwind - Widget chrome — color-scheme and selection on the widget root
- HTML Custom Element Embed
- Development Integration
- API Reference — the public widget GET, including
cssProperties - Projects, Environments & Tokens
- The Composer