Skip to content

Sass Placeholder Selectors

Placeholder selectors, written with a leading %, exist purely to be shared through @extend. This lesson explains how they differ from regular classes and mixins, and why they produce smaller compiled CSS than an equivalent mixin in many cases.

What Is a Placeholder Selector?

A placeholder selector looks like a class selector but starts with % instead of .. On its own, a placeholder never appears in the compiled CSS output, it only becomes real CSS once another selector @extends it, at which point the extending selector is merged into the placeholder's rule.

%button-reset {
  border: none;
  background: none;
  cursor: pointer;
  font: inherit;
}

.btn-icon {
  @extend %button-reset;
  padding: 0.25rem;
}

The compiled output merges .btn-icon directly into the %button-reset rule, so no duplicate declarations are generated even if many selectors extend the same placeholder.

Placeholder Selector Syntax

%placeholder-name {
  // declarations
}

.selector {
  @extend %placeholder-name;
}
  • Placeholder selectors start with % instead of . or #.
  • A placeholder never appears alone in the compiled CSS unless something @extends it.
  • Multiple selectors can @extend the same placeholder; the compiler groups them into one combined rule.
  • Placeholders can be nested, receive &, and use interpolation exactly like regular selectors.

Placeholder Selectors Cheatsheet

How placeholders compare to classes and mixins for sharing styles.

Aspect Placeholder (%foo + @extend) Mixin (@mixin + @include)
Output per use Selector grouped into one shared rule Declarations duplicated at every call site
Appears alone in CSS? No, unless directly extended N/A, mixins aren't selectors
Accepts parameters? No Yes
Best for Pure style inheritance with no variation Reusable styles that vary by input

Placeholders vs Regular Classes

You could @extend a regular class instead of a placeholder, but that leaves the original class selector in your compiled CSS even if you never intend to use it directly in HTML. Placeholders exist specifically to avoid that leftover, unused selector.

// Using a regular class (leaves .btn-base in the output, even if unused directly)
.btn-base {
  padding: 0.5rem 1rem;
}

// Using a placeholder (never appears alone in the output)
%btn-base {
  padding: 0.5rem 1rem;
}

.btn-primary {
  @extend %btn-base;
  background: #2563eb;
}

Smaller Output Than Equivalent Mixins

Because @extend groups every extending selector into one shared rule, using a placeholder for styles that never vary produces smaller compiled CSS than an equivalent parameterless mixin, which would duplicate the same declarations at every @include call site.

// Mixin: duplicates declarations at every call site
@mixin btn-base {
  padding: 0.5rem 1rem;
  border-radius: 4px;
}

// Placeholder: declarations exist once, selectors are grouped together
%btn-base {
  padding: 0.5rem 1rem;
  border-radius: 4px;
}

When to Choose Placeholders Over Mixins

Placeholders are ideal for styles that never need parameters, pure, fixed inheritance. As soon as you need to vary the output based on an argument, a mixin (or a function) is the correct tool instead.

Common Mistakes

  • Extending a regular class instead of a placeholder, leaving an unused, standalone selector in the compiled CSS.
  • Trying to pass arguments to a placeholder through @extend, which isn't supported, placeholders never accept parameters.
  • Using @extend across very different, unrelated selectors just to save a few lines, producing confusing, overly specific combined selectors in the output.
  • Forgetting that a placeholder can itself use nesting, &, and media queries, and assuming it's limited to flat declarations only.

Key Takeaways

  • Placeholder selectors (%name) exist purely to be shared through @extend and never appear alone in compiled CSS.
  • Extending a placeholder groups every extending selector into one combined rule, avoiding duplicated declarations.
  • Unlike mixins, placeholders cannot accept parameters, they are best for fixed, unvarying shared styles.
  • Prefer a placeholder over a regular class specifically to avoid leaving an unused selector in your output CSS.

Pro Tip

Reach for a placeholder and @extend specifically when several unrelated selectors need identical, parameter-free styles, if you ever need to vary even one property between uses, switch to a mixin instead.