Skip to content

Less - Scope

Scope in LESS refers to the visibility and accessibility of variables and mixins. LESS uses lexical (or static) scoping, meaning that variables and mixins are resolved based on where they are defined in the code structure. When LESS encounters a variable, it first looks for it in the current, local scope. If not found, it progressively searches in parent scopes, up to the global scope.

A unique aspect of LESS variable scoping is often described as “lazy evaluation” or, more accurately, “last declaration wins within the same or accessible parent scope.” This means that the value of a variable is determined by its last definition encountered before or during the parsing of the block that uses it, within the accessible scopes. This allows for flexibility in defining variables, even after their first usage within the same block or in an imported file.

The following example demonstrates how variable scope and the “last declaration wins” principle work in LESS:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LESS Scope Example</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<header>
<h1>Scope Demonstration</h1>
</header>
<div class="content-block">
<p class="main-text">This text uses a font size defined by a variable.</p>
<div class="inner-block">
<p>This inner text might have a different style.</p>
</div>
</div>
</body>
</html>
// Global scope
@base-color: #333;
@default-padding: 10px;
header {
@header-color: blue; // Local to header
color: @header-color;
padding: @default-padding; // Uses global @default-padding
}
.content-block {
@block-padding: 15px; // Local to .content-block
padding: @block-padding;
color: @base-color; // Uses global @base-color
.main-text {
// LESS 'lazy evaluation' demonstration:
// @font-size is used before its final definition within this scope.
font-size: @dynamic-size;
@temp-size: 14px;
@dynamic-size: @temp-size + 2px; // First definition: 14px + 2px = 16px
}
// Re-definition of @dynamic-size within the same .content-block scope
// This will be the value used by .main-text because it's the last declaration encountered
// before the .content-block scope fully resolves.
@another-var: 10px;
@dynamic-size: @another-var + 8px; // Last definition: 10px + 8px = 18px
.inner-block {
@block-padding: 5px; // Local to .inner-block, shadows .content-block's @block-padding
padding: @block-padding;
background-color: lighten(@base-color, 80%);
font-size: @dynamic-size; // Uses the @dynamic-size from .content-block (18px)
}
}

Compile style.less to style.css using: lessc style.less style.css

/* Global scope styles */
header {
color: blue;
padding: 10px;
}
.content-block {
padding: 15px;
color: #333;
}
.content-block .main-text {
font-size: 18px; /* Used the last definition of @dynamic-size from .content-block */
}
.content-block .inner-block {
padding: 5px;
background-color: #cccccc;
font-size: 18px; /* Also uses the 18px @dynamic-size from .content-block */
}
  • Lexical Scoping: Variables like @header-color are local to header. @block-padding defined in .inner-block shadows the one in .content-block only within .inner-block.
  • Global Scope: @base-color and @default-padding are global and accessible everywhere unless shadowed locally.
  • Last Declaration Wins (within accessible scope): In .content-block, @dynamic-size is used by .main-text. Even though an initial calculation for @dynamic-size (16px) occurs before its use, the final definition of @dynamic-size (18px) within the .content-block scope is what gets compiled. This is because LESS processes all variable declarations within a scope before outputting rules for that scope.
  • Nested Scopes: .inner-block can access @dynamic-size from its parent (.content-block) because it doesn’t define its own @dynamic-size.

Understanding variable scope is essential for writing predictable and maintainable LESS. The “last declaration wins” rule offers flexibility but should be used carefully to avoid confusion in complex stylesheets. Organizing variables logically (e.g., in a dedicated _variables.less file imported at the top) is a common best practice.