← Back to Sass Mastery
Intermediate12 min read

Inheritance & Extend

Share styles between selectors with @extend and placeholder selectors — understand when to extend versus mixin for optimal output.

The @extend Directive

@extend merges selectors that share common styles. When .btn-primary { @extend .btn; } compiles, both selectors share a single rule block rather than duplicating declarations.

Extend is powerful but can produce unexpected selector combinations in complex stylesheets. The compiled output may group selectors in ways that increase specificity unexpectedly.

.btn {
  display: inline-flex;
  padding: 0.75rem 1.5rem;
  border-radius: 8px;
  font-weight: 600;
}

.btn-primary {
  @extend .btn;
  background: $color-primary;
  color: white;
}

Placeholder Selectors

Placeholder selectors (%) are extend-only — they never appear in compiled CSS unless extended. This prevents orphaned base classes and keeps HTML clean.

Always extend placeholders rather than concrete classes. Extending a real class like .btn creates a dependency on that class existing in HTML.

  • Placeholders (%) compile away if never extended
  • Extending placeholders keeps HTML free of utility classes
  • Each extended placeholder adds the extender to the shared rule
%button-base {
  display: inline-flex;
  align-items: center;
  border: none;
  cursor: pointer;
  font-family: inherit;
}

.btn-primary {
  @extend %button-base;
  background: $color-primary;
}

.btn-secondary {
  @extend %button-base;
  background: transparent;
  border: 1px solid $color-primary;
}

Extend vs Mixin

Mixins duplicate CSS output for each @include. Extends group selectors to share output. For small, frequently used patterns (clearfix, visually-hidden), extends produce smaller CSS. For parameterized patterns, mixins are the only option.

The Sass community generally recommends mixins over extends for most cases due to predictability. Use extends sparingly for silent utility classes.

// Mixin: outputs each time (larger CSS)
@mixin sr-only { /* ... */ }

// Extend: groups selectors (smaller CSS)
%sr-only { /* ... */ }
.label { @extend %sr-only; }
.caption { @extend %sr-only; }
// Compiles to: .label, .caption { ... }

Multiple Inheritance

A selector can extend multiple placeholders. Sass merges all extended rules into the compiled output. Be cautious — extending many placeholders from widely used selectors creates large grouped selector lists.

Keep extend chains shallow. If A extends B and B extends C, the compiled selector list grows combinatorially.

%typography-base {
  font-family: $font-stack;
  line-height: 1.6;
}

%interactive {
  cursor: pointer;
  transition: opacity 200ms ease;
}

.tab {
  @extend %typography-base;
  @extend %interactive;
}

When to Use Each

Use mixins for: parameterized patterns, media queries, and anything included fewer than three times. Use extends for: silent utility classes used across many selectors where smaller output matters.

In modern Sass projects, CSS custom properties and utility-first CSS have reduced the need for both. Reach for @extend only when bundle size analysis shows meaningful savings.

// Modern alternative: CSS custom properties
:root {
  --btn-padding: 0.75rem 1.5rem;
  --btn-radius: 8px;
}

.btn {
  padding: var(--btn-padding);
  border-radius: var(--btn-radius);
}

Get In Touch


Ready to discuss your next project? Drop me a message.