SyntaxStudy
Sign Up
SASS / SCSS @extend vs @mixin — Choosing the Right Tool
SASS / SCSS Beginner 1 min read

@extend vs @mixin — Choosing the Right Tool

Both `@extend` and `@mixin` enable reuse of styles, but they are optimised for different scenarios. `@extend` produces efficient, grouped selectors in the output and is best for styles that are truly shared and identical across multiple elements — structural or typographic bases with no variations. `@mixin` is best for parametric styles where the output varies per call site, or for styles that include logic, loops, or `@content` blocks. A key practical concern with `@extend` is its behaviour across modules. In modern SASS using `@use`, you cannot extend a placeholder from a different module — `@extend` only works within the same compilation context. This makes `@extend` less suitable for component libraries where each component is a separate file. Mixins do not have this restriction. The SASS team's own guidance leans towards preferring mixins for most use cases in module-based codebases, reserving `@extend` with placeholders for cases where selector grouping in the output genuinely matters for file size. When in doubt, the mixin approach is safer and more portable, especially as projects grow in size and complexity.
Example
// ── Decision guide: @extend vs @mixin ────────────────────────────────────────

// USE @extend + %placeholder when:
// - Styles are identical (no variation per use)
// - All uses are in the same file / compilation unit
// - Output CSS size is a concern

%card-shell {
    border-radius: 8px;
    padding      : 1.5rem;
    background   : #fff;
    box-shadow   : 0 2px 8px rgba(0,0,0,.08);
}

.product-card  { @extend %card-shell; display: flex; flex-direction: column; }
.profile-card  { @extend %card-shell; text-align: center; }
.summary-card  { @extend %card-shell; border-left: 4px solid #3498db; }

// USE @mixin when:
// - Styles vary per use (parametric)
// - Use spans multiple files / modules
// - Mixin includes @content, loops, or conditional logic

@mixin elevation($level: 1) {
    $shadows: (
        1: 0 1px 3px rgba(0,0,0,.12),
        2: 0 4px 12px rgba(0,0,0,.15),
        3: 0 8px 24px rgba(0,0,0,.2)
    );
    box-shadow: map.get($shadows, $level);
}

.tooltip   { @include elevation(1); }
.dropdown  { @include elevation(2); }
.modal     { @include elevation(3); }

// ── Why @extend fails across modules ─────────────────────────────────────────
// In modern SASS with @use, this will throw an error:
//
// _cards.scss:
//   @use 'placeholders';
//   .card { @extend placeholders.%card-shell; }  ← NOT allowed
//
// Solution: Move placeholders into the same file, or switch to a mixin.