The ${...} expression produces values at compile time inside .luis. It works inside @fun, @for, and @if; it can also be used directly in selector and declaration values.
This page also covers the former Expression Engine content.
Supported Expression Types
Section titled “Supported Expression Types”| Type | Example |
|---|---|
| Arithmetic | ${i + j}, ${i * 4}, ${i / 2} |
| String concatenation | ${'btn' + '-' + size} |
| Compile-time normal var | ${var(--prefix) + '-' + name} |
| Compile-time object key var | ${var(--theme.prefix) + '-' + name} |
| Compile-time array index var | ${var(--sizes[0])}, ${var(--sizes[ind])} |
| Compile-time array item key | ${var(--breakpoints[0].name)}, ${var(--breakpoints[ind].name)} |
| Compile-time object bracket | ${var(--colors[key])} |
| Local array index access | ${arr[0]} |
| Local array index + key | ${arr[0].name} |
| Local object key access | ${obj.key}, ${obj.name} |
| Parenthesized expression | ${(i + j) * 2} |
General Notes
Section titled “General Notes”${...}can be used not only inside@foror@funbut also in selector and declaration values- If the expression produces a string or calculation result, it is written to output at compile time
- When concatenating with a string literal, the literal part must be quoted:
'btn',"sm" - Unquoted tokens like
color,prefix,btnare interpreted as identifiers, not string literals
General Usage
Section titled “General Usage”Can also be used outside @for or @fun
--prefix: btn;--factor: 4;
.${var(--prefix) + '-size'} { font-size: ${var(--factor) * 4}px;}Generated CSS:
.btn-size { font-size: 16px; }Basic Arithmetic
Section titled “Basic Arithmetic”The four arithmetic operators are supported: +, -, *, /
@for(i, [1-4]) { .p-${i} { padding: ${i * 4}px; } .gap-${i} { gap: ${i * 8}px; }}Generated CSS:
.p-1 { padding: 4px; }.p-2 { padding: 8px; }.p-3 { padding: 12px; }.p-4 { padding: 16px; }.gap-1 { gap: 8px; }.gap-2 { gap: 16px; }.gap-3 { gap: 24px; }.gap-4 { gap: 32px; }Standard operator precedence applies: * and / first, then + and -. Use parentheses in ambiguous cases:
@for(i, [1-3]) { .item-${(i + 1) * 2} { z-index: ${(i + 1) * 2}; }}Generated CSS:
.item-4 { z-index: 4; }.item-6 { z-index: 6; }.item-8 { z-index: 8; }Special Rule for the - Operator
Section titled “Special Rule for the - Operator”The - operator behaves differently depending on context:
| Form | Behavior |
|---|---|
${a - b} | Mathematical subtraction if all operands are numbers |
${prefix-name} | Concatenation with - if at least one is a string |
${prefix + '-' + name} | Always string concatenation — explicit form, recommended |
Use the explicit form in ambiguous cases:
/* Ambiguous — is prefix a string or number? */.${prefix-size} { }
/* Explicit and always correct */.${prefix + '-' + size} { }Special Rule for the + Operator
Section titled “Special Rule for the + Operator”The + operator behaves differently depending on context:
| Form | Behavior |
|---|---|
${a + b} | Mathematical addition if all operands are numbers |
${prefix+name} | Concatenation if at least one is a string |
--prefix: btn;--factor: 4;--count: 6;
.${var(--prefix) + '-size'} { font-size: ${var(--factor) * 4}px;}
.${var(--prefix) + var(--factor)} { font-size: ${var(--factor) * 4}px;}
.size-${var(--count) + var(--factor)} { font-size: ${var(--factor) * 4}px;}Output:
.btn-size { font-size: 16px;}
.btn4 { font-size: 16px;}
.size-10 { font-size: 16px;}Multiplication With Units
Section titled “Multiplication With Units”A value with a unit can be multiplied by a unitless number. The unit is carried to the output.
@fun: size(i) { ${i * 4};}
.btn { padding: @fun.size(3px); margin: @fun.size(2px);}Generated CSS:
.btn { padding: 12px; margin: 8px;}With an array variable:
--scale: [1px-4px];--factor: 3;
@for(i, var(--scale)) { .space-${i} { margin-top: ${i} * var(--factor); }}Generated CSS:
.space-1px { margin-top: 3px; }.space-2px { margin-top: 6px; }.space-3px { margin-top: 9px; }.space-4px { margin-top: 12px; }Two var() can be multiplied directly in a declaration value — ${...} is not required:
--scale: [1px-3px];--factor: 4;
.space { margin-top: var(--factor) * var(--scale[0]);}Generated CSS:
.space { margin-top: 4px;}var() multiplication with ${...} inside @for:
--scale: [1px-3px];--factor: 4;
@for(i, var(--scale)) { .space-${i} { margin-top: ${i * var(--factor)}; }}Generated CSS:
.space-1px { margin-top: 4px; }.space-2px { margin-top: 8px; }.space-3px { margin-top: 12px; }String Concatenation
Section titled “String Concatenation”String values are concatenated with the + operator. String literals must be quoted.
--prefix: btn;
@for(size, [sm, md, lg]) { .${var(--prefix) + '-' + size} { font-size: 14px; }}Generated CSS:
.btn-sm { font-size: 14px; }.btn-md { font-size: 14px; }.btn-lg { font-size: 14px; }Inside @fun:
@fun: make-class(prefix, name) { .${prefix + '__' + name} { display: block; }}
@fun.make-class(card, body);@fun.make-class(card, footer);Generated CSS:
.card__body { display: block; }.card__footer { display: block; }Compile-Time var() Access Forms
Section titled “Compile-Time var() Access Forms”The following var() forms are supported inside ${...}:
${var(--prefix) + '-' + size} /* CSS variable */${var(--theme.prefix) + '-' + size} /* Object key */${var(--sizes[0])} /* Array index */${var(--sizes[ind])} /* Array index (loop variable) */${var(--breakpoints[0].name)} /* Array item key */${var(--breakpoints[ind].name)} /* Array item key (loop variable) */${var(--colors[key])} /* Object bracket — only for object variables */Usage in Selector and Declaration Value
Section titled “Usage in Selector and Declaration Value”--color: A;
.${'color' + var(--color)} { color: ${'#aa' + var(--color)};}.colorA { color: #aaA; }--colorA: [A-F];
.${"color-" + var(--colorA[0])} { color: ${"#aa" + var(--colorA[0])};}.color-A { color: #aaA; }Dynamic Object Key
Section titled “Dynamic Object Key”--colors: { primary: #111111; secondary: #222222; };
@for(key, [primary, secondary]) { .text-${key} { color: ${var(--colors[key])}; }}.text-primary { color: #111111; }.text-secondary { color: #222222; }Calculation in Nested Loops
Section titled “Calculation in Nested Loops”Multiple iteration values can be calculated together in nested @for loops.
--x: [1-2];--y: [1-3];
@for(i, var(--x)) { @for(j, var(--y)) { .m-${i + '-' + j} { padding: ${i * j}px; } }}Generated CSS:
.m-1-1 { padding: 1px; }.m-1-2 { padding: 2px; }.m-1-3 { padding: 3px; }.m-2-1 { padding: 2px; }.m-2-2 { padding: 4px; }.m-2-3 { padding: 6px; }${i + '-' + j} in the selector does string concatenation, while ${i * j} in the property does multiplication.
Calculation With Parenthesized Expression
Section titled “Calculation With Parenthesized Expression”Parentheses determine precedence in expressions with multiple operations.
--space: [0-3];
@for(i, var(--space)) { .p-${i} { padding: ${(i + 2) * 3}px; }}Generated CSS:
.p-0 { padding: 6px; }.p-1 { padding: 9px; }.p-2 { padding: 12px; }.p-3 { padding: 15px; }For i = 0: (0 + 2) * 3 = 6, for i = 1: (1 + 2) * 3 = 9.
Calculation With Local Variables
Section titled “Calculation With Local Variables”Local variables can be used inside @fun to store intermediate calculation results.
@fun: make-spacing(base) { $sm: ${base}; $md: ${base * 2}; $lg: ${base * 4};
.space-sm { margin: ${sm}px; } .space-md { margin: ${md}px; } .space-lg { margin: ${lg}px; }}
@fun.make-spacing(4);Generated CSS:
.space-sm { margin: 4px; }.space-md { margin: 8px; }.space-lg { margin: 16px; }