Skip to content

Less - Passing Rulesets to Mixins

LESS - Passing Rulesets to Mixins (Detached Rulesets)

Section titled “LESS - Passing Rulesets to Mixins (Detached Rulesets)”

Less features a powerful concept called ‘Detached Rulesets’. This allows you to define a block of CSS rules—including properties, nested selectors, variable declarations, and even other mixin calls—and store this entire block within a variable. You can then ‘call’ this variable as if it were a mixin, effectively injecting its contents into another ruleset. Detached rulesets are particularly useful for advanced theming, creating highly configurable components, or passing complex style configurations as a single unit.

The following example demonstrates how to define and use a detached ruleset in a LESS file. The example shows a detached ruleset that itself contains a mixin definition, which is then used.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css" type="text/css" />
<title>LESS Detached Rulesets</title>
</head>
<body>
<div class="content-container">
<h2>Welcome to Advanced Less!</h2>
<p>This section is styled using a detached ruleset.</p>
</div>
</body>
</html>

Next, create the style.less file.

// Define a detached ruleset and store it in the @theme-styles variable.
// This detached ruleset itself contains a mixin definition.
@theme-styles: {
// This .apply-styling mixin is defined *inside* the detached ruleset.
.apply-styling() {
font-family: Verdana, sans-serif; // Using a more common font
background-color: #E0F7FA; // A light cyan background
border: 1px solid #00796B;
padding: 15px;
}
// You could also define variables or other rules here.
@internal-variable: #004D40; // Example internal variable
};
.content-container {
// First, 'call' or 'unlock' the detached ruleset itself.
// This makes everything inside @theme-styles (like .apply-styling and @internal-variable)
// available within the current scope (.content-container).
@theme-styles();
// Now, call the .apply-styling() mixin which was defined inside @theme-styles.
.apply-styling();
// You can also use variables defined within the detached ruleset:
color: @internal-variable; // This will use #004D40
}

To compile style.less to style.css, use the command:

lessc style.less style.css

This command will generate the style.css file:

.content-container {
font-family: Verdana, sans-serif;
background-color: #E0F7FA;
border: 1px solid #00796B;
padding: 15px;
color: #004D40;
}

When index.html is viewed in a browser:

  • The div with class .content-container will have the styles defined in the .apply-styling() mixin (font, background color, border, padding) and the text color from @internal-variable.
  • This demonstrates how a detached ruleset can encapsulate a set of styles and behaviors, making them portable and reusable in a structured way.

Understanding scope is crucial when working with detached rulesets:

  • Definition vs. Caller Scope: A detached ruleset is defined in its own scope (the ‘declaration scope’). When you ‘call’ or ‘unlock’ a detached ruleset (e.g., @theme-styles();), its contents (variables, mixins) become available in the scope where it’s called (the ‘caller scope’).
  • Precedence: If both the declaration scope (inside the detached ruleset) and the caller scope contain a variable or mixin with the same name, the one from the declaration scope generally takes priority for resolving names within the detached ruleset itself. However, when the detached ruleset is applied, it operates within the context of the caller’s scope and can access variables from the caller’s scope if not found internally.
  • Referencing Doesn’t Change Scope: If you assign one detached ruleset variable to another (e.g., @another-set: @theme-styles;), this is just a reference. The @another-set doesn’t gain a new scope; it still points to the original detached ruleset with its original declaration scope.
  • ‘Unlocking’ and Scope Access: When you ‘unlock’ a detached ruleset by calling it with parentheses (@ruleset()), it effectively merges its styles into the current scope and can access variables and mixins from this calling scope if they are not defined within the detached ruleset itself. This allows for dynamic styling based on the context where the detached ruleset is used.

Detached rulesets offer a sophisticated way to manage complex style collections and apply them conditionally or dynamically, forming a powerful part of Less’s pre-processing capabilities.