LESS has no @if or @else statement. Instead, it uses guarded mixins: multiple definitions of the same mixin, each with a when condition, and only the matching definitions apply. This lesson introduces the guard mechanism in depth.
What Is a Mixin Guard?
A guard is written after a mixin's parameter list using the when keyword, followed by a condition in parentheses. When the mixin is called, LESS evaluates each guarded definition's condition and only applies the ones that evaluate to true.
This design keeps LESS declarative, similar to how @media query conditions work, rather than introducing imperative if/else control flow into a styling language.
.badge(@bg) when (lightness(@bg) >= 50%) {
color: black;
}
.badge(@bg) when (lightness(@bg) < 50%) {
color: white;
}
.badge(@bg) {
background: @bg;
padding: 0.25rem 0.5rem;
}
.warning { .badge(#facc15); } // light background, gets black text
.danger { .badge(#7f1d1d); } // dark background, gets white text
Both guarded definitions and the unguarded definition apply together whenever their conditions match, or always, for the unguarded one.
Guard Syntax
.mixin(@a) when (condition) {
property: value;
}
The when keyword introduces a guard condition immediately after the parameter list.
A mixin definition without a guard always matches, and can coexist alongside guarded versions of the same name.
Multiple guarded definitions of the same mixin name can all match and apply simultaneously if their conditions overlap.
The keyword true is the only truthy value; .mixin(@a) when (@a) is shorthand for .mixin(@a) when (@a = true).
Mixin Guards Cheatsheet
Core guard patterns you'll use across conditional mixins.
Pattern
Example
Notes
Comparison guard
when (@a > 0)
Numeric comparison
Type-check guard
when (iscolor(@a))
Matches only if @a is a color
Boolean guard
when (@a)
True only if @a is exactly the keyword true
AND logic
when (@a > 0) and (@a < 10)
Both conditions must be true
OR logic
when (@a > 10), (@a < -10)
Comma acts as logical or
NOT logic
when not (@a = 0)
Negates the condition
Unguarded fallback
.mixin(@a) { }
Always matches, no when clause
Combining Guards with Logical Operators
Guards support and to require multiple conditions simultaneously, a comma , to act as a logical or (matching if any listed condition is true), and not to negate a condition.
.status(@code) when (@code >= 200) and (@code < 300) {
color: green; // success range
}
.status(@code) when (@code >= 400), (@code >= 500) {
color: red; // client or server error
}
Type-Checking Functions in Guards
LESS provides built-in is* functions to branch mixin behavior based on the type of an argument, useful when a mixin should accept either a color or a keyword like none.
iscolor(), isnumber(), isstring(), iskeyword(), isurl(), and unit-specific checks like ispixel() are all built in.
Matching on Exact Argument Values
Guards can compare an argument against a literal keyword or value, which is a common pattern for building a small, guard-based variant system, similar to a switch statement.
Trying to write an @else clause; LESS has no such syntax, use another guarded definition with the opposite condition instead.
Forgetting that multiple guarded definitions with overlapping conditions can all match and apply together, not just the first match.
Using = for a boolean check instead of the simpler when (@a) shorthand when a value is expected to be the keyword true.
Confusing and (all conditions must match) with , (any condition matches), which behave oppositely.
Key Takeaways
Guards use the when keyword to conditionally apply a mixin definition based on its arguments.
Multiple guarded definitions can coexist, and more than one can match and apply for a single call.
and requires all conditions to be true; a comma , acts as a logical or between conditions.
Built-in is* functions let guards branch based on an argument's type, not just its value.
Pro Tip
When building a guard-based variant system (primary, success, danger), always add an unguarded fallback definition too, so unexpected argument values still receive sensible default styles instead of silently matching nothing.
You now understand mixin guards and conditional logic in LESS. Next, learn how namespaces group related mixins together.