Sass selector.replace() Function

Intermediate
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
sass:selector · Dart Sass 1.23+

What You’ll Learn

selector.replace() belongs to the built-in sass:selector module. It returns a copy of a selector with one piece swapped for another, using the same intelligent unification as @extend. This page covers the three arguments, vs selector.extend, and five compiled examples.

01

Concept

Swap, don’t keep

02

Module

@use "sass:selector"

03

Returns

Selector value

04

Args

sel, original, replacement

05

vs extend

Swap vs add-on

06

Practice

5 examples

What Is selector.replace()?

Official docs: returns a copy of $selector with all instances of $original replaced by $replacement. It uses the @extend rule’s intelligent unification so the replacement fits into the surrounding selector. If $selector never contains $original, the value is returned unchanged.

  • Three arguments: the selector to rewrite, what to find, and what to put instead.
  • Placeholder selectors are allowed; parent selectors (&) are not.
  • See also selector.extend() when you want to keep the original and add a form.
💡
Beginner tip

Think find-and-replace for selectors: a.disabled with a.link becomes .disabled.link—the a is gone, .disabled stays.

📝 Syntax

styles.scss
@use "sass:selector";

// Recommended
selector.replace($selector, $original, $replacement)

// Legacy global name
selector-replace($selector, $original, $replacement)

Parameters

ParameterTypeRequiredDescription
$selectorSelectorYesSelector to rewrite.
$originalSelectorYesThe piece to find and remove/replace.
$replacementSelectorYesWhat to put in place of $original.

Return value

TypeResult
SelectorReplaced selector (or the original if $original was absent)

📦 Loading sass:selector

styles.scss
// Recommended — namespaced (Dart Sass 1.23+)
@use "sass:selector";
$sel: selector.replace("a.disabled", "a", ".link");
// .disabled.link

// Optional — bring members into scope
@use "sass:selector" as *;
$sel: replace("a.disabled", "a", ".link");

// Legacy global
$sel: selector-replace("a.disabled", "a", ".link");

🎨 Official Patterns

CallResult (Dart Sass)
replace("a.disabled", "a", ".link").disabled.link
replace("a.disabled", "h1", "h2")a.disabled (unchanged)
replace(".guide .info", ".info", ".content nav.sidebar").guide .content nav.sidebar, .content .guide nav.sidebar

Unlike extend, the first sample does not keep a.disabled—only the replaced form remains. Dart Sass may print compound classes in a different simple-selector order (for example .disabled.link); matching is the same as .link.disabled.

⚖️ replace vs extend

HelperTypical result for a.disabled / a.linkUse when
selector.replace.disabled.linkSwap the original piece out completely
selector.extenda.disabled, .disabled.linkKeep the original and add the extender form

🛠 Compatibility

This is about Sass compilers, not browsers. The rewrite runs at compile time.

Implementationreplace
Dart SassYes — prefer selector.replace (module since 1.23.0)
LibSassLegacy selector-replace may exist; no @use "sass:selector"
Ruby SassLegacy selector-replace may exist; no @use "sass:selector"

Prefer current Dart Sass so the module API matches the official docs.

⚡ Quick Reference

GoalCode
Import selector@use "sass:selector";
Swap a compound pieceselector.replace("a.disabled", "a", ".link")
No match (safe)selector.replace("a.disabled", "h1", "h2") → unchanged
Use as a selector#{selector.replace(…)} { … }
Keep original tooselector.extend(…)

Examples Gallery

Each example uses selector.replace at compile time (Dart Sass 1.23+). Open View Compiled CSS for verified output.

📚 Getting Started

Official docs samples, then real CSS rules.

Example 1 — Official Replace Samples

Match found, no match, and complex unification.

styles.scss
@use "sass:selector";

.probe {
  --link: #{selector.replace("a.disabled", "a", ".link")};
  --miss: #{selector.replace("a.disabled", "h1", "h2")};
  --guide: #{selector.replace(".guide .info", ".info", ".content nav.sidebar")};
}

How It Works

When $original is present, it is swapped out (not kept). When it is missing, nothing changes. Complex replacements can expand into more than one complex selector.

Example 2 — Build Rule Selectors

Interpolate the replaced result into a real style rule.

styles.scss
@use "sass:selector";

#{selector.replace(".btn.primary", ".btn", ".cta")} {
  background: teal;
}

How It Works

.btn is replaced by .cta, so only the CTA form remains—not .btn.primary.

📈 Practical Patterns

Mixins, extend contrast, and alternate class loops.

Example 3 — Swap Base Mixin

Wrap replace so callers pass selector, original, and replacement.

styles.scss
@use "sass:selector";

@mixin swap-base($selector, $original, $replacement) {
  #{selector.replace($selector, $original, $replacement)} {
    color: inherit;
  }
}

@include swap-base("a.disabled", "a", ".link");

How It Works

Same official first sample, packaged as a reusable mixin for aliasing base selectors.

Example 4 — Replace vs Extend

Same arguments, different intent.

styles.scss
@use "sass:selector";

.compare {
  --replace: #{selector.replace("a.disabled", "a", ".link")};
  --extend: #{selector.extend("a.disabled", "a", ".link")};
}

How It Works

replace drops a.disabled. extend keeps it and adds the link form.

Example 5 — Alternate Class Loop

Replace one base class with several alternate names.

styles.scss
@use "sass:selector";

$base: ".card.featured";
$alts: ".promo", ".highlight";

@each $alt in $alts {
  #{selector.replace($base, ".card", $alt)} {
    border-width: 2px;
  }
}

How It Works

Each alternate fully replaces .card while keeping .featured. Unlike extend, .card.featured is not kept in the output.

🚀 Real-World Use Cases

  • Class aliases — map .btn.primary styles onto .cta.primary only.
  • Theme swaps — replace a brand base class without leaving the old selector.
  • Mixin APIs — accept selector strings and emit swapped rule lists.
  • Complex layouts — unify nested replacements like the official guide/info sample.
  • Safe defaults — no-op when $original is absent (returns the original).

🧠 How Compilation Works

1

Pass three selectors

Call selector.replace($selector, $original, $replacement).

Source
2

Sass unifies the swap

Finds $original, drops it, and integrates $replacement.

Compile
3

Interpolate into rules

Use #{…} as the selector for a style block.

Emit
4

CSS ships

Browsers only see finished selectors like .disabled.link.

⚠️ Common Pitfalls

  • Confusing with extend — replace drops the original; extend keeps it.
  • Parent selectors& is not allowed in these arguments.
  • Wrong argument order — remember selector, then original, then replacement.
  • Forgetting interpolation — wrap results in #{…} to use them as rule selectors.
  • Expecting plain string replace — this is selector unification, not text search.

💡 Best Practices

✅ Do

  • Use @use "sass:selector" and selector.replace()
  • Use it when you want a full swap
  • Prefer extend when keeping the original matters
  • Pass clean selectors without parent &
  • Prefer Dart Sass 1.23+

❌ Don’t

  • Pass parent selectors (&)
  • Assume every miss is an error—unchanged return is intentional
  • Treat it like JavaScript string replace
  • Expect browsers to evaluate the call
  • Rely on LibSass for the module API

Key Takeaways

Knowledge Unlocked

Five things to remember about selector.replace()

Swap selector pieces with @extend-style unification—the original match is dropped.

5
Core concepts
📦 02

Module

sass:selector

@use
🔗 03

Result

original dropped

Output
📚 04

Miss

returns as-is

Detail
05

Alt

extend to keep

Compare

❓ Frequently Asked Questions

selector.replace($selector, $original, $replacement) returns a copy of $selector with all instances of $original replaced by $replacement, using @extend-style intelligent unification. Example: replace("a.disabled", "a", ".link") becomes .disabled.link.
replace swaps the original out. extend keeps the original and adds the extender form. Same args: replace → .disabled.link; extend → a.disabled, .disabled.link.
Official docs: if $selector does not contain $original, the function returns $selector unchanged.
No. Arguments may contain placeholder selectors, but not parent selectors.
Yes. selector-replace($selector, $original, $replacement) is the legacy global name. Prefer selector.replace after @use "sass:selector".
Dart Sass 1.23+. LibSass and Ruby Sass do not load sass:selector with @use; they may still offer the legacy global name.
Did you know?

Official Sass docs say selector.replace uses the same intelligent unification as the @extend rule—so complex replacements can produce multiple unified selectors, not just a simple text swap.

Conclusion

selector.replace() rewrites selectors by swapping $original for $replacement with @extend-style unification. Prefer selector.extend when you need to keep the original, and avoid parent selectors.

Continue with selector.simple-selectors() or the Sass introduction.

Next: simple selectors

Learn selector.simple-selectors() to split a compound into simple parts.

selector.simple-selectors() →

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.

5 people found this page helpful