Extend & Inheritance

@extend shares a set of styles between selectors a different way than a mixin does — instead of copying the properties into each selector, it groups every selector that shares them into one combined rule.

Placeholder selectors

A placeholder selector, written with % instead of ., exists only to be extended — it never compiles into CSS on its own:

SCSS buttons.scss
%button-base {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
}

.btn-primary {
  @extend %button-base;
  background: #1b6ec2;
  color: white;
}

.btn-secondary {
  @extend %button-base;
  background: #565d72;
  color: white;
}
Compiled CSS
.btn-primary, .btn-secondary {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
}

.btn-primary {
  background: #1b6ec2;
  color: white;
}

.btn-secondary {
  background: #565d72;
  color: white;
}

Compare this to a mixin: instead of the five shared properties being copied into .btn-primary and again into .btn-secondary, Sass combined both selectors into a single rule that lists the shared properties once. The result is smaller compiled CSS whenever many selectors share the exact same base styles.

Extending a real class instead of a placeholder

You can also @extend an ordinary class selector, not just a placeholder — though a placeholder is usually the better choice specifically because it never generates its own unused CSS rule if nothing happens to extend it:

SCSS alerts.scss
.message {
  padding: 12px;
  border-radius: 4px;
}

.error {
  @extend .message;
  background: #fdecea;
  color: #a33b3b;
}
Compiled CSS
.message, .error {
  padding: 12px;
  border-radius: 4px;
}

.error {
  background: #fdecea;
  color: #a33b3b;
}

Here .message compiles into real CSS on its own (since it's a genuine class, presumably used directly in HTML somewhere) as well as being combined with .error.

Note: @extend's selector-combining behavior can produce a less predictable compiled order than a mixin's straightforward copy-paste, especially once several files and partials are extending the same placeholder — the combined selector list ends up ordered by where each extending selector was defined, not necessarily where you'd expect. For a shared block of styles used across many unrelated selectors, many teams reach for a mixin instead purely because its output is easier to reason about, even though it does produce more repeated CSS.