QSS — QORM Style Sheets
QSS is QORM's stylesheet language: a CSS-like rule syntax for sharing styles across scenes, without repeating inline style blocks on every node.
A stylesheet lives in styles/<id>.qss and is loaded by the runtime at load time. The Tetris example (examples/tetris/styles/app.qss) is a complete, runnable reference — a game's entire look driven by one stylesheet.
Rule syntax
# This is a comment
/* selectors: type, class, id */
button { borderRadius: 12 }
.accent { background: var(--primary); color: var(--on-primary) }
#submit { fontSize: 16 }
/* nested objects stay inline on the node, like style values */
.card { margin: { top: 8, bottom: 8 } }
/* {{bindings}} evaluate like inline style values */
.statValue { color: {{ state.dark ? "#fff" : "#111" }} }
- Type selectors (
button,text,box, …) match nodes of that type. - Class selectors (
.accent) match nodes whoseclassprop lists that
name (space-separated; a class named later in the prop wins).
- ID selectors (
#submit) match a node'sid. #comments — numbers stay numbers, strings and{{bindings}}evaluate
like inline style values.
Cascade
Style resolution is a cascade, later sources winning key by key:
theme component default < type rule < class rule < id rule < inline `style`
- Within one class name, declaration order wins; the node's own
classlist
order wins between classes.
- Inline
styleon the node always beats every rule.
Using a stylesheet
Scene nodes reference rules with a class prop:
{ "type": "text", "text": "TETRIS", "class": "title" }
Canvas rendering
The native canvas backend (-tags desktop) applies QSS rules in its measure pass — theme component defaults, then type/class/id rules, then inline style — exactly the cascade above. The HTML renderer uses inline styles only.
Diagnostics
Parse errors are load-time diagnostics naming BOTH the file and the line ([Stylesheet: app] app.qss:3: …). Unknown style keys (against render.KnownStyleKeys) are warnings. The rules parsed before and after an error still load, exactly like a scene keeps loading alongside its own diagnostics — one bad rule never blanks the app.
Loader contract
- A
.qssfile is collected only inside astyles/directory. - Its id is the file name (minus
.qss):styles/app.qss→ stylesheetapp. - Duplicate ids are an error diagnostic on directory load (first wins) and a
hard refusal from qorm build.
- The raw source is kept on the app so the serializer writes each sheet back
verbatim — the same fixed-point property component documents have.