Home Sass Selector selector.extend() Sass selector.extend() Definition
Definition and Usage selector.extend($selector, $extendee, $extender) returns a copy of $selector rewritten as if this ran:
#{$extender} {
@extend #{$extendee};
} In other words: keep the original, and add unified forms that use $extender. Load with @use "sass:selector".
Official sample idea. selector.extend("a.disabled", "a", ".link") → a.disabled, .disabled.link (keeps the original and adds the extender form).
Miss = unchanged. If $selector does not contain $extendee, the function returns $selector as-is.
No parent selectors. Placeholders are allowed; & is not. Need a swap instead of keep-and-add? Use selector.replace() .
Syntax
Syntax @use "sass:selector";
selector.extend($selector, $extendee, $extender) //=> selector
selector.extend("a.disabled", "a", ".link");
// a.disabled, .disabled.link
selector.extend("a.disabled", "h1", "h2");
// a.disabled (unchanged — no match)
selector.extend(".guide .info", ".info", ".content nav.sidebar");
// .guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar
// Use as a rule selector:
#{selector.extend(".btn.primary", ".btn", ".cta")} { ... }
// Global alias (legacy): selector-extend($selector, $extendee, $extender)
// Prefer selector.extend after @use "sass:selector" Pattern: pick what to extend → Sass keeps the original and adds extender forms → interpolate with #{…} for CSS rules.
Code
SCSS Examples Examples use @use "sass:selector". Open View Compiled CSS for verified Dart Sass output (matches official Sass docs samples where shown).
1. Official 2. Rules 3. Mixin 4. vs replace 5. Loop Example 1 — Official Extend Samples Match found, no match, and complex unification.
@use "sass:selector";
.probe {
--link: #{selector.extend("a.disabled", "a", ".link")};
--miss: #{selector.extend("a.disabled", "h1", "h2")};
--guide: #{selector.extend(".guide .info", ".info", ".content nav.sidebar")};
} .probe {
--link: a.disabled, .disabled.link;
--miss: a.disabled;
--guide: .guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar;
} How It Works Hit : a is found → keep original + add .disabled.link.Miss : no h1 → return unchanged.Complex : .info is extended by a multi-part selector.Matches the official Sass docs sample idea.Example 2 — Build Rule Selectors Interpolate the extended result into a real style rule.
@use "sass:selector";
#{selector.extend(".btn.primary", ".btn", ".cta")} {
background: teal;
} .btn.primary, .primary.cta {
background: teal;
} How It Works .btn is the extendee inside .btn.primary..cta extends it → .primary.cta is added.Original kept : .btn.primary still matches.#{…} turns the list into one CSS rule.Example 3 — Share Styles Mixin Wrap extend so callers pass selector, extendee, and extender.
@use "sass:selector";
@mixin share-styles($selector, $extendee, $extender) {
#{selector.extend($selector, $extendee, $extender)} {
color: inherit;
}
}
@include share-styles("a.disabled", "a", ".link"); a.disabled, .disabled.link {
color: inherit;
} How It Works Mixin packages the three arguments.Same result as the official first sample.Reusable for design-system helpers.Compile-time only — browsers see finished selectors.Example 4 — Extend vs Replace Same arguments, different intent.
@use "sass:selector";
.compare {
--extend: #{selector.extend("a.disabled", "a", ".link")};
--replace: #{selector.replace("a.disabled", "a", ".link")};
} .compare {
--extend: a.disabled, .disabled.link;
--replace: .disabled.link;
} How It Works extend keeps a.disabled.replace drops the original match.Both produce .disabled.link.Choose extend when you need keep-and-add.Example 5 — Alternate Class Loop Extend one base selector with several alternate class names.
@use "sass:selector";
$base: ".card.featured";
$alts: ".promo", ".highlight";
@each $alt in $alts {
#{selector.extend($base, ".card", $alt)} {
border-width: 2px;
}
} .card.featured, .featured.promo {
border-width: 2px;
}
.card.featured, .featured.highlight {
border-width: 2px;
} How It Works $base is the selector to rewrite.@each supplies alternate extenders..featured stays on original and new forms.Useful for promo / highlight class aliases. Edge Cases & Pitfalls Most extend bugs are confusing it with replace or passing &.
miss No match = no change If $extendee is absent, the selector returns unchanged.
& Parent selectors forbidden Placeholders are fine; do not pass &.
#{} Interpolate for rules Wrap results in #{…} to emit CSS selectors.
Toolchain
Sass Support Prefer the module form with current Dart Sass.
API Status selector.extend()Dart Sass 1.23+ via @use "sass:selector" Return type Selector Parent selectors Not allowed Legacy global selector-extend($selector, $extendee, $extender)
Compile with the Dart Sass CLI .
Remember
Key Takeaways @extend-style rewrite — keep original, add extender forms.
Miss stays unchanged when $extendee is absent.
vs replace — replace drops the original match.
Prefer @use "sass:selector" (Dart Sass 1.23+).
One line: to rewrite a selector like @extend, use selector.extend($selector, $extendee, $extender).
Practice
Compile Notes Practical checklist:
1. @use "sass:selector"
2. Pass $selector, $extendee, $extender
3. Expect keep-and-add (not a swap)
4. Interpolate with #{} for CSS rules
5. Use replace when you want substitution only Frequently Asked Questions What does Sass selector.extend() do? selector.extend($selector, $extendee, $extender) returns a copy of $selector rewritten as if $extender { @extend $extendee; } ran. It keeps matches of $extendee and adds forms that use $extender. Example: extend("a.disabled", "a", ".link") becomes a.disabled, .disabled.link.
How is it different from selector.replace()? extend keeps the original selector and adds extended variants (a.disabled, .disabled.link). replace swaps $original for $replacement and drops the original match (.disabled.link only).
What if $extendee is missing? If $selector does not contain $extendee, the function returns $selector unchanged.
Can I use & parent selectors? No. Arguments may contain placeholder selectors, but not parent selectors.
Is there a global selector-extend()? Yes. selector-extend($selector, $extendee, $extender) is the legacy global name. Prefer selector.extend after @use "sass:selector".
Which compilers support the module API? Dart Sass 1.23+. LibSass and Ruby Sass do not load sass:selector with @use; they may still offer the legacy global name.
Next: Sass selector.is-superselector() Check whether one selector matches everything another matches.
is-superselector() → About the author Developer, cloud engineer, and technical writer
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
Helpful Share Copy link Suggestion