Sass Placeholder Selectors — Silent Extend-Only Classes
In this tutorial, you will learn about Sass Placeholder Selectors. We cover key concepts, practical examples, and best practices to help you master this topic.
Sass placeholder selectors use % prefix to create classes that exist only for @extend, producing no CSS output unless explicitly extended by another selector.
What You'll Learn
You will learn how to define and use placeholder selectors, understand their output benefits, combine them with mixins, and build extendable pattern libraries.
Why It Matters
Placeholders avoid unused CSS. DodaTech's component library uses placeholders for all base patterns so the compiled CSS only includes what is actually used.
Real-World Use
Durga Antivirus Pro's design system defines button, card, and form base patterns as placeholders. Components that @extend them produce only the needed output.
flowchart LR
A[@extend] --> B[Placeholders]
B --> C[% Selectors]
B --> D[No Output]
B --> E[Library Use]
B --> F[Patterns]
style B fill:#c69,stroke:#c69,color:#fff
style C fill:#22c55e,stroke:#16a34a,color:#fff
Placeholder Basics
// Define a placeholder (no CSS output)
%button-base {
display: inline-block;
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
// Extend the placeholder
.btn-primary {
@extend %button-base;
background: #7c3aed;
color: white;
}
.btn-danger {
@extend %button-base;
background: #ef4444;
color: white;
}
Compiles to:
.btn-primary, .btn-danger {
display: inline-block;
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
.btn-primary { background: #7c3aed; color: white; }
.btn-danger { background: #ef4444; color: white; }
Expected output: No .button-base class in the compiled CSS. Only the extending classes exist.
Placeholders vs Regular Classes
// Regular class — always outputs
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
}
// Placeholder — only outputs if extended
%sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
}
// If nothing extends %sr-only, it produces zero CSS
Expected output: The regular class always appears. The placeholder only appears if extended.
Placeholder Library Pattern
// _placeholders.scss
%clearfix {
&::after {
content: "";
display: table;
clear: both;
}
}
%text-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
%flex-center {
display: flex;
justify-content: center;
align-items: center;
}
%visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
// main.scss
@import "placeholders";
.card-header {
@extend %clearfix;
}
.ellipsis-text {
@extend %text-truncate;
}
.icon-wrapper {
@extend %flex-center;
}
Expected output: Only the three required patterns appear in the compiled CSS, not the entire placeholder library.
Placeholder with Mixins
// Mixin that extends a placeholder
@mixin button-variant($bg, $color) {
@extend %button-base;
background: $bg;
color: $color;
}
%button-base {
display: inline-block;
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-primary { @include button-variant(#7c3aed, white); }
.btn-success { @include button-variant(#10b981, white); }
Expected output: Both buttons share the base styles from the placeholder, with unique backgrounds from the mixin.
Placeholder for Responsive Patterns
%container {
width: 100%;
margin: 0 auto;
padding: 0 1rem;
@media (min-width: 768px) { max-width: 720px; }
@media (min-width: 992px) { max-width: 960px; }
@media (min-width: 1200px) { max-width: 1140px; }
}
.main-content {
@extend %container;
}
.sidebar {
@extend %container;
}
Expected output: Both .main-content and .sidebar share the responsive container pattern.
Placeholder Nesting
%card {
background: white;
border-radius: 8px;
overflow: hidden;
%card-body {
padding: 1rem;
}
%card-header {
padding: 1rem;
background: #f8fafc;
border-bottom: 1px solid #e2e8f0;
}
}
.user-card {
@extend %card;
.body { @extend %card-body; }
.head { @extend %card-header; }
}
Expected output: Nested placeholders are scoped to the parent placeholder context.
Common Mistakes
1. Extending Placeholders From Different Files
Placeholders defined in one file must be @imported or @used before @extend. Order matters.
2. Using Placeholder Names That Conflict
Placeholder names use the same namespace as classes. A %button and .button cannot coexist in the same scope.
3. Forgetting That Placeholders Are Global
Placeholders are globally accessible regardless of where they are defined. Use namespaced names.
4. Extending Placeholders Inside Media Queries
Defining a placeholder inside a media query and extending it outside causes errors.
5. Overusing Placeholders for Everything
Use placeholders only for patterns that are extended multiple times. Single-use patterns do not benefit.
Practice Questions
What prefix identifies a placeholder selector? The
%prefix, like%button-base { ... }.Does a placeholder appear in compiled CSS if not extended? No. Placeholders produce no CSS output unless extended.
Why are placeholders useful for libraries? Libraries can define many patterns as placeholders. Only the patterns actually used produce CSS output.
Can placeholders be nested? Yes. Placeholders can be nested inside other placeholders.
Can a mixin extend a placeholder? Yes. Mixins can include @extend directives for placeholders.
Challenge
Build a utility placeholder library with 10 common patterns (clearfix, truncate, flex-center, visually-hidden, container, card-base, button-base, input-base, list-reset, transition). Write a test page that uses 6 of them and verify unused placeholders do not appear in CSS.
FAQ
Mini Project
Create a utility-first "functional CSS" library using placeholders. Define placeholders for common patterns (text alignment, display values, spacing, colors). Consumers @extend what they need. Verify the compiled CSS only includes used utilities.
What's Next
Learn Sass Control Directives for conditional logic with @if, @else if, @else. Then explore Sass Loops for iteration.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro