Detached rulesets
A detached ruleset is a block of declarations and rules in braces stored in a variable. You can call it anywhere or pass it to a mixin as an argument. The main benefit is a mixin that wraps your block of styles, for example in a media query. In Sass this is what @content is for.
A ruleset in a variable
Store a block of styles in a variable and call it with parentheses:
// styles/main.less
@focus-ring: {
outline: 2px solid #2563eb;
outline-offset: 2px;
};
.btn:focus-visible {
@focus-ring();
}
.field:focus-visible {
@focus-ring();
}.btn:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
.field:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}<style>
.btn:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
.field:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
</style>
<button class="btn">Press Tab</button>
<input class="field" placeholder="Post title">Press Tab to move to the button and the field: each gets a blue focus outline.
A block of styles as a mixin argument
A mixin can take a ruleset and insert it inside a media query. Describe it in styles/mixins.less:
// styles/mixins.less
.desktop(@rules) {
@media (min-width: 768px) {
@rules();
}
}Pass the block in braces right in the call:
// styles/components/cards.less
.card {
padding: 16px;
.desktop({
padding: 32px;
display: flex;
});
}// styles/main.less
@import "mixins";
@import "components/cards";.card {
padding: 16px;
}
@media (min-width: 768px) {
.card {
padding: 32px;
display: flex;
}
}The breakpoint is written once — in the mixin. If it changes, you edit one line instead of every media query.
Nested rules inside a ruleset
A ruleset can hold not only declarations but also rules with &:
// styles/main.less
@hover-dark: {
&:hover {
background: #111827;
}
};
.btn {
background: #2563eb;
@hover-dark();
}.btn {
background: #2563eb;
}
.btn:hover {
background: #111827;
}& was replaced by the selector of the rule where the ruleset was called.
Common mistake
A ruleset is called only with parentheses. Without them Less reads the line as a map lookup and stops:
// styles/main.less
@focus-ring: {
outline: 2px solid #2563eb;
};
.btn:focus-visible {
@focus-ring;
}Compilation fails with the error Missing '[...]' lookup in variable call. Write @focus-ring();.