Output & evaluation cheat sheet
A quick reference for how Jess formats output and how it evaluates the trickier corners, each with a tiny input → output. The shared formatting and evaluation rules are the same engine as the Less site; the Jess-flavored specifics (interpolation spelling, Sass+ strictness) are at the end.
Output formatting
Un-operated values are source-verbatim
Un-operated dimensions, colors, keywords, and quoted strings emit exactly as written; only computed results (and compressed output) canonicalize.
.a { width: 1.0px; height: 2PX; color: #989; }
.a { width: 1.0px; height: 2PX; color: #989; }
See Verbatim values.
Operators and separators are spaced
/, +, -, *, and list commas print with surrounding spaces, no matter
how you wrote them — they are separators, not values.
.a { margin: 12px/16px; grid-area: 1/2/3/4; }
.a { margin: 12px / 16px; grid-area: 1 / 2 / 3 / 4; }
Exception: :nth-*() An+B stays unspaced
The An+B microsyntax is selector syntax — never spaced, never evaluated.
.a:nth-child(2n+1) { color: red; }
.a:nth-child(2n+1) { color: red; }
Function shape passes through verbatim
name(...) with no space before ( emits verbatim, even for names that are
not real CSS functions.
.a { border: 1px solid(#a8000b); }
.a { border: 1px solid(#a8000b); }
Grouping parens dissolve after evaluation
keyword (expr) — a space then parens — is math grouping. Parens are
dropped when the calculation in them is resolved: a $( … ) that computes, a
function that runs, or a variable or member that names one value ($w: 10vh; height: ($w) → height: 10vh). (A no-space keyword(expr) is the function
shape above and stays verbatim.) Parens around something that computes nothing —
one value, a CSS function such as var(), math kept as written, a variable that
names a list — stay as you wrote them, as they do in plain CSS. The same holds
inside a math function: math written in calc() is not computed, so
calc(100% - ((1px + 2px))) keeps its parens, while
calc(100% - (($(1px + 2px)))) is calc(100% - 3px) and calc(($(1px + 2px)))
is calc(3px). Text is never a computed value, and it prints as written: parens
around an escaped string, such as $e("1px + 2px"), stay wherever it is written,
so calc(2 * ($e("1px + 2px"))) is calc(2 * (1px + 2px)) and ($e("foo")) is
(foo). Only where the text is spliced into a selector, a property name or a
string, or read by a function, the group gives its text.
$a: #a80000; $b: #00000b;
.a { border: 1px solid ($($a * .66 + $b * .33)); }
.a { border: 1px solid #6f0004; }
$w: 10vh;
.a { height: ($w); width: ($(1px + 2px)); top: var(--top, (10px)); left: (10px); }
.a { height: 10vh; width: 3px; top: var(--top, (10px)); left: (10px); }
Color functions pass through un-operated
CSS-shaped rgb/rgba/hsl/hsla with three or more argument slots and no
operation emit verbatim; the function runs when the value is operated on or
given a Less overload/variable argument. Less one-/two-slot overloads such as
rgba(#fff) dispatch normally.
.a { color: hsl(200, 50%, 40%); } // verbatim
.b { color: lighten(hsl(200,50%,40%), 10%); } // computed
Nested output + :is() compaction
Output is nested by default (collapseNesting: false); @media is not merged;
extend cascades are :is()-compacted. See Output model
and Extend.
Evaluation
Escaped ~"..." is opaque
An escaped string is never sniffed as a number. = compares by content
(3 = ~"3" is true); </> against a number is not comparable, so a guard
using them does not fire.
Mixin self-reference is a no-op
A non-parametric ruleset that calls itself excludes its own frame — it renders once and never errors.
Mixin variable leaks are low priority
A variable a mixin unlocks into the caller is low priority: a lexical binding always wins, and the leaked variable is used only where nothing lexical binds.
if() / boolean() are branch-lazy
The branch not taken is never evaluated.
.a { width: if(false, 1/0, 7px); }
.a { width: 7px; }
@import (reference) is hidden until pulled in
Reference imports emit nothing on their own; their rules appear only where you
$extend them or call an imported mixin.
Resolve failures are errors
Any failed variable resolve is a hard error unless the resolve is explicitly
optional. There are no cyclic variables — $a: 1; $a: $a + 1; yields 2. See
Advanced variable resolution.
Jess-flavored specifics
- Three
$forms, one per position:${…}interpolates in identifier positions (selectors, property names, at-rule preludes) and in strings;$[…](lookup) and$(...)(expression) are value-position forms, and$(...)is also allowed in strings. Inside${…},${tone}is the variable and${[tone]}the lookup — see Interpolation. - Variables:
$nameis a live reference;$^nameis the scoped/final lookup.$name := valueupdates the live/current binding;$^name := valueupdates the scoped/final binding. - Sass+ rejects invalid CSS: where Sass tolerates invalid CSS (escaped at-rule keywords, bogus combinators), Jess's "Sass+" dialect rejects it — valid CSS is the target, not Sass parity.