Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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();.

Thanks for reading!

Donate to the site — we work hard for you.