Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Extending with :extend

Extending adds your selector to a rule that already exists. A mixin copies declarations into every place it is called, while :extend writes the declarations once and lists all the selectors separated by commas. The CSS gets shorter when several classes look the same.

Extending a rule

Describe a base button and extend it in styles/components/buttons.less:

// styles/components/buttons.less
.btn {
  padding: 8px 16px;
  border-radius: 8px;
}
 
.btn-primary:extend(.btn) {
  color: white;
  background: #2563eb;
}
.btn,
.btn-primary {
  padding: 8px 16px;
  border-radius: 8px;
}
.btn-primary {
  color: white;
  background: #2563eb;
}
<style>
  .btn,
  .btn-primary {
    padding: 8px 16px;
    border-radius: 8px;
  }
  .btn-primary {
    color: white;
    background: #2563eb;
  }
</style>
 
<button class="btn-primary">Publish</button>

The .btn-primary selector was added to the .btn rule, and its own declarations stayed in a separate rule. One class in the HTML is enough.

Writing it inside a rule

The same thing can be written inside a rule with &:extend(). This is handier when there are several classes to extend:

// styles/components/buttons.less
.btn {
  padding: 8px 16px;
}
 
.rounded {
  border-radius: 8px;
}
 
.btn-danger {
  &:extend(.btn, .rounded);
  background: #dc2626;
}
.btn,
.btn-danger {
  padding: 8px 16px;
}
.rounded,
.btn-danger {
  border-radius: 8px;
}
.btn-danger {
  background: #dc2626;
}

The all keyword

Without extra words :extend matches only exactly the same selector. To capture derived rules too, such as .btn:hover, add all:

// styles/components/buttons.less
.btn {
  background: #2563eb;
 
  &:hover {
    background: #1d4ed8;
  }
}
 
.link-button:extend(.btn all) {}
.btn,
.link-button {
  background: #2563eb;
}
.btn:hover,
.link-button:hover {
  background: #1d4ed8;
}

.link-button received both the normal background and the hover background.

Extend or mixin

:extendMixin
What reaches the CSSThe selector is added to an existing ruleThe declarations are copied
ParametersNoYes
CSS size with many callsHardly growsGrows with every call
Works inside @media with an outside ruleNoYes

In Sass the same job is done by @extend, which is written inside a rule.

Common mistake

:extend looks for the selector in the final CSS. A pure mixin with parentheses never reaches the CSS, so extending it does nothing:

// styles/components/buttons.less
.flex-center() {
  display: flex;
  align-items: center;
}
 
.badge:extend(.flex-center) {
  width: 32px;
}
.badge {
  width: 32px;
}

Less only prints the warning extend ' .flex-center' has no matches, and the badge stays without centring. For pure mixins use the call .flex-center();, and keep :extend for ordinary classes.

Thanks for reading!

Donate to the site — we work hard for you.