@fun lets you define reusable CSS blocks. The defined function is called with parameters and expanded at compile time.
Definition
Section titled “Definition”@fun: function-name(param1, param2) { /* body */}Rules:
-can be used in function names@for,@if,elseif,elsecan be used inside the body- If argument count is too few or too many, the function is not expanded and a
function-argument-mismatchwarning is produced
Argument mismatch example:
@fun: make-chip(name, bg, fg) { .chip-${name} { background: ${bg}; color: ${fg}; }}
/* ✓ Correct — 3 arguments */@fun.make-chip(primary, #dbe9ff, #1c3f8f);
/* ✗ Too few arguments — not expanded, function-argument-mismatch warning produced */@fun.make-chip(primary, #dbe9ff);
/* ✗ Too many arguments — not expanded, function-argument-mismatch warning produced */@fun.make-chip(primary, #dbe9ff, #1c3f8f, 8px);On mismatch, the relevant @fun.make-chip(...) call does not appear in CSS output; other correct calls are unaffected.
Block Generation
Section titled “Block Generation”The function body generates selector blocks or properties. Called as an independent statement.
@fun: make-chip(name, bg, fg) { .chip-${name} { background: ${bg}; color: ${fg}; padding: 4px 12px; border-radius: 12px; }}
@fun.make-chip(success, #d1fae5, #065f46);@fun.make-chip(danger, #fee2e2, #991b1b);Generated CSS:
.chip-success { background: #d1fae5; color: #065f46; padding: 4px 12px; border-radius: 12px;}
.chip-danger { background: #fee2e2; color: #991b1b; padding: 4px 12px; border-radius: 12px;}Inline Value Return
Section titled “Inline Value Return”The function body produces a value expression. Called as the value of a property.
@fun: size(i) { ${i * 4}px;}
.btn { padding: @fun.size(3); margin: @fun.size(2);}Generated CSS:
.btn { padding: 12px; margin: 8px;}Property Inline Return
Section titled “Property Inline Return”The function body is written as property: value form. Called as a statement; expanded as the full property block.
@fun: font-size-s(i) { font-size: 12px * ${i};}
.title-s { color: #000; @fun.font-size-s(2);}Generated CSS:
.title-s { color: #000; font-size: 24px;}Multiple property: value can be written:
@fun: sizes(i) { font-size: 12px * ${i}; margin: ${i * 4px};}
.title-s { color: #000; @fun.sizes(2);}Generated CSS:
.title-s { color: #000; font-size: 24px; margin: 8px;}Passing Parameters With var(...)
Section titled “Passing Parameters With var(...)”Variable values can be passed to function parameters via var(...).
--primary: #dbe9ff;--secondary: #1c3f8f;--call: 5;
@fun: make-chip(name, bg, fg, call) { .chip-${name} { background: ${bg}; color: ${fg}; margin: ${call * 2}px; }}
@fun.make-chip(primary, var(--primary), var(--secondary), var(--call));Generated CSS:
:root { --primary: #dbe9ff; --secondary: #1c3f8f; --call: 5;}
.chip-primary { background: var(--primary); color: var(--secondary); margin: 10px;}Part of the variable name inside var(...) can also be generated via a placeholder:
--colors-light: { bg: #f8f9fa; text: #212529; };--colors-dark: { bg: #0f1117; text: #e9ecef; };
@fun: theme-bg(t) { background-color: var(--colors-${t}.bg); color: var(--colors-${t}.text);}
.card-light { @fun.theme-bg(light); }.card-dark { @fun.theme-bg(dark); }Generated CSS:
.card-light { background-color: #f8f9fa; color: #212529;}
.card-dark { background-color: #0f1117; color: #e9ecef;}Combination With @for
Section titled “Combination With @for”A function can be called from inside a @for loop. The function is expanded independently for each iteration.
@fun: make-density(mode) { @if(${mode} === 'compact') { .density-${mode} { padding: 2px 6px; } } else { .density-${mode} { padding: 6px 10px; } }}
@for(mode, [compact, relaxed]) { @fun.make-density(${mode});}Generated CSS:
.density-compact { padding: 2px 6px; }.density-relaxed { padding: 6px 10px; }Nesting and At-Rule Generation
Section titled “Nesting and At-Rule Generation”The function body can also contain nested selectors and at-rules:
@fun: card-layout(bp, pad) { @media (min-width: ${bp}) { .card { padding: ${pad};
.title { font-size: 18px; } } }}
@fun.card-layout(768px, 24px);Generated CSS:
@media (min-width: 768px) { .card { padding: 24px; }
.card .title { font-size: 18px; }}This pattern is suitable for reusing the same nested-at-rule pattern with different breakpoints or values.
Local Variables
Section titled “Local Variables”Local variables can be defined inside @fun bodies with the $name syntax. Local variables are accessed with ${name}.
@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; }Warning Codes
Section titled “Warning Codes”| Situation | Warning |
|---|---|
| Undefined function called | unknown-function-call |
| Argument count mismatch | function-argument-mismatch |
| Two functions with the same name defined | duplicate-function |
| Invalid function syntax | invalid-function-syntax |
| Invalid function name | invalid-function-name |
| Recursion | function-recursion |