Skip to content

LESS Extend

The :extend() pseudo-class lets one selector inherit another selector's matching rule, merging them together in the compiled output instead of duplicating declarations the way a mixin call would.

What Does :extend() Do?

When you write .button:extend(.base-button) {}, LESS finds every compiled rule where .base-button appears and adds .button to that same selector list. The declarations themselves are written only once in the output.

This is different from calling a mixin, which copies the mixin's declarations into every selector that calls it, duplicating the actual CSS properties in the output.

.message {
  padding: 1rem;
  border-radius: 4px;
}

.success {
  &:extend(.message);
  border-color: green;
}

Compiles to .message, .success { padding: 1rem; border-radius: 4px; } plus a separate .success { border-color: green; } rule.

Extend Syntax

.selector:extend(.other-selector);
.selector { &:extend(.other-selector); }
.selector:extend(.other-selector all);
  • Extend can be written directly on a selector, or nested with &:extend(...) inside a rule's block.
  • The all keyword extends every occurrence of the target selector, including nested combinations.
  • Multiple extends can be chained: &:extend(.a):extend(.b);.
  • Extending a selector that doesn't exist anywhere is silently ignored, it produces no error and no output.

LESS Extend Cheatsheet

Common extend patterns and what they compile to.

Pattern Example Notes
Basic extend .a:extend(.b); Adds .a to every rule matching .b
Nested extend .a { &:extend(.b); } Same result, written inside the block
Extend all .a:extend(.b all); Also matches .b used in compound selectors
Chained extend .a:extend(.b):extend(.c); Extends multiple targets at once
Mixin vs extend .mixin(); vs &:extend(.class); Mixin duplicates declarations; extend merges selectors

Extend vs Mixins: Output Size

Choosing between a mixin call and :extend() is mostly about compiled output size. A mixin copies its full declaration block into every caller; extend merges selectors so the declarations exist exactly once.

// Mixin approach: declarations duplicated for each caller
.message() { padding: 1rem; border-radius: 4px; }
.success { .message(); border-color: green; }
.error { .message(); border-color: red; }

// Extend approach: declarations written once, selectors merged
.message { padding: 1rem; border-radius: 4px; }
.success:extend(.message) { border-color: green; }
.error:extend(.message) { border-color: red; }

The extend version's compiled CSS repeats padding and border-radius zero times instead of twice.

Using the all Keyword

By default, :extend() only matches a selector when it appears standalone. Adding the all keyword also matches the target selector when it's part of a compound or nested selector elsewhere in the file.

.a { color: blue; }
.wrapper .a { font-weight: 700; }

.b:extend(.a all) {}
// .b now matches BOTH ".a { color: blue; }"
// and ".wrapper .a { font-weight: 700; }"

When to Choose Extend Over a Mixin

Extend is the better choice when a group of selectors share identical static declarations with no parameters. Once you need arguments, defaults, or conditional logic, a parametric mixin is the right tool instead.

  • Use extend for shared, parameter-free declaration blocks (like a base alert or message style).
  • Use mixins when you need to pass arguments, like a color or size.
  • Use mixins when the shared logic includes guards or conditional behavior.

Common Mistakes

  • Using :extend() when a mixin's parametric behavior (colors, sizes) is actually needed instead.
  • Forgetting the all keyword when trying to extend a selector that only ever appears as part of a compound selector.
  • Assuming extend copies declarations like a mixin does; it actually merges selectors, producing zero duplication.
  • Extending a placeholder-style class that doesn't otherwise exist in the compiled output, silently producing no effect.

Key Takeaways

  • :extend() merges a selector into every compiled rule matching its target, instead of duplicating declarations.
  • It can be written directly on a selector or nested with &:extend(...) inside a block.
  • The all keyword also matches the target selector inside compound and nested selectors.
  • Choose extend for shared static styles, and a parametric mixin when arguments or guards are needed.

Pro Tip

Reach for :extend() when several selectors need identical, parameter-free base styles (like alerts or badges); it keeps compiled CSS smaller than the equivalent mixin calls.