Sass Placeholder Selectors

Beginner
9 min read
Updated: Nov 2026
5 examples
Dart Sass

Definition and Usage

A placeholder selector looks like a class but starts with %. It is not written to CSS unless another selector @extends it.

Silent until extended.

Any complex selector that contains a % placeholder is omitted from the output. Style rules whose selectors all contain placeholders disappear entirely until extended.

Library-friendly.

Placeholders share styles without forcing a fixed HTML class name. Consumers @extend %name from their own selectors.

App vs library.

For a single app with a real class already in the HTML, extending that class is often simpler. Prefer % for optional / reusable style packs.

Syntax

SCSS
%toolbelt {
  box-sizing: border-box;
  padding: 16px 0;

  &:hover { border: 2px solid; }
}

.action-buttons {
  @extend %toolbelt;
  color: #4285f4;
}

Pattern: define %name { ... } → @extend %name from real selectors → Sass merges those selectors into the compiled CSS.

Common Patterns

Where placeholders usually appear:

PatternResult idea
%name { ... }Silent styles; nothing emitted alone
@extend %namePull placeholder styles into this selector
.a, %b { ... }Only .a emits until %b is extended
%name { &:hover }Nested states apply to every extender
%a { @extend %b }Chain placeholders; still silent until a real selector extends

SCSS Examples

Open View Compiled CSS for verified Dart Sass output (matches official Sass docs samples where shown).

Example 1 — Official Silent Mix

A selector list with a placeholder only emits the non-placeholder part.

SCSS
.alert:hover, %strong-alert {
  font-weight: bold;
}

%strong-alert:hover {
  color: red;
}

How It Works

  1. %strong-alert is dropped from the list.
  2. %strong-alert:hover emits nothing alone.
  3. .alert:hover remains in the CSS.
  4. Matches the official Sass docs sample.

Example 2 — Official %toolbelt + @extend

Two classes extend one placeholder, including nested &:hover.

SCSS
%toolbelt {
  box-sizing: border-box;
  border-top: 1px rgba(#000, .12) solid;
  padding: 16px 0;
  width: 100%;

  &:hover { border: 2px rgba(#000, .5) solid; }
}

.action-buttons {
  @extend %toolbelt;
  color: #4285f4;
}

.reset-buttons {
  @extend %toolbelt;
  color: #cddc39;
}

How It Works

  1. %toolbelt alone would emit nothing.
  2. @extend merges both classes into the rule.
  3. &:hover becomes hover rules for each extender.
  4. Matches the official Sass docs sample.

Example 3 — One Class Extends a Card

Minimal pattern: define %, extend from a real class.

SCSS
%card {
  padding: 1rem;
  border-radius: 8px;
}

.panel {
  @extend %card;
  background: #fff;
}

How It Works

  1. %card holds shared layout styles.
  2. .panel extends them and adds its own color.
  3. No %card appears in the CSS.
  4. HTML only needs class="panel".

Example 4 — Unused Placeholder Emits Nothing

If nothing extends %, it leaves no CSS behind.

SCSS
%unused {
  color: red;
}

.used {
  color: blue;
}

How It Works

  1. %unused is never extended.
  2. Output keeps only .used.
  3. A class like .unused would always emit.
  4. Why libraries prefer placeholders for optional packs.

Example 5 — Chain Placeholders

One placeholder can extend another; a real selector still starts emission.

SCSS
%base {
  display: block;
}

%base-em {
  @extend %base;
  font-style: italic;
}

.quote {
  @extend %base-em;
}

How It Works

  1. %base-em extends %base.
  2. .quote extends %base-em.
  3. Both placeholder rules flow into .quote.
  4. No % names appear in the CSS.

Edge Cases & Pitfalls

Most placeholder bugs are expecting CSS from an unextended %.

silent

No @extend means no CSS

Defining %card alone never styles the page. Something must @extend it.

HTML

% is not a class name

Do not write class="%toolbelt" in HTML. Extend from a real selector instead.

lists

Mixed lists drop the %

.a, %b keeps only .a until %b is extended.

app

Prefer a class for single-app UI

If the class already exists in markup, extending that class is often clearer than inventing a placeholder.

Sass Support

Placeholder selectors and @extend are core Sass features on Dart Sass.

FeatureStatus
%name selectorsSupported
@extend %nameSupported—see @extend
Nesting / & inside placeholdersSupported
Unused placeholdersOmitted from CSS

Compile with the Dart Sass CLI.

Key Takeaways

  • % is a silent class-like selector.
  • @extend %name pulls those styles into real selectors.
  • Unused % leaves no CSS clutter.
  • Libraries love placeholders; single apps often extend a real class.

One line: use % when you want shareable styles that stay out of CSS until something @extends them.

Compile Notes

Practical checklist:

checklist.txt
1. Define shared styles under %name { ... }
2. From a real selector, write @extend %name;
3. Nest &:hover (and friends) inside the placeholder if needed
4. Confirm unused placeholders do not appear in CSS
5. For app-only classes, consider extending a real class instead

Frequently Asked Questions

Selectors that start with % (for example %toolbelt). They look and behave much like class selectors, but they are not written to the CSS output unless another selector extends them.
Unused placeholders leave no CSS behind. Classes always emit. Placeholders also avoid forcing library users to put a specific class name in their HTML—they @extend the placeholder from their own selectors.
Define styles under %name { ... }, then write .my-class { @extend %name; }. Sass merges .my-class into the placeholder’s selector list in the compiled CSS.
Only the complex selectors that do not contain a placeholder are emitted. Example: .alert:hover, %strong-alert { } compiles to just .alert:hover { } unless something extends %strong-alert.
If the stylesheet is only for your own app and a real class already exists in the HTML, extending that class is often simpler. Prefer placeholders when writing reusable libraries or optional style packs.
Yes. %toolbelt { &:hover { ... } } works. Extenders inherit those nested rules too, so .action-buttons:hover appears in the output when you @extend %toolbelt.

Next: Sass Nesting

Nest style rules so selectors compose without repeating the parent.

Nesting →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful