Placeholder Selectors and @extend

A placeholder selector begins with % and is not emitted as a standalone selector unless it is extended by another selector. It is useful for sharing a set of declarations among related selectors.

The @extend directive allows a selector to inherit the selector rules associated with another selector. Sass may combine selectors in generated CSS, which can create larger selector groups than expected.

Mixins and placeholders serve different purposes. Mixins copy declarations into each inclusion point, whereas placeholders and @extend participate in selector unification. Neither is universally superior.

Prefer mixins when the caller needs different parameter values or when explicit component output is desirable. Consider placeholders for tightly related selectors that genuinely share a structural rule set. Avoid extending broad selectors across unrelated components.

Mixin
Output: Declarations expanded at include sites
The generated rules can be easy to associate with each component.
Parameters: Supported
Values and behavior can be configured per inclusion.
Placeholder and extend
Output: Selectors unified
Sass combines rules involving extending selectors.
Parameters: Not a mixin-style parameter API
Use a mixin when per-call configuration is required.
Sharing Declarations with a Placeholder
%message-base {
  padding: 1rem;
  border-radius: 0.5rem;
}

.success-message {
  @extend %message-base;
  color: #155724;
  background: #d4edda;
}

.error-message {
  @extend %message-base;
  color: #721c24;
  background: #f8d7da;
}
💡 The placeholder's declarations are shared by the extending selectors. The placeholder itself does not appear as a standalone selector in the generated CSS. Inspect compiled CSS when using @extend, especially when extending selectors with complex relationships. Selector unification can produce output that is less obvious from the SCSS source.
Knowledge Check

What happens to a placeholder selector such as `%message-base` when it is not extended?