Sass Parent Selector

Beginner
⏱️ 14 min read
📚 Updated: Jul 2026
🎯 5 Examples
& selector

What You’ll Learn

The Sass parent selector (&) refers to the outer selector inside nested rules. Use it for pseudo-classes, BEM suffixes, parent context, SassScript introspection, and advanced nesting with selector.unify. Five compiled examples follow.

01

& basics

Replace parent

02

Pseudo

&:hover

03

Suffixes

BEM &__

04

Context

[dir] &

05

SassScript

& / null

06

Practice

5 examples

What Is the Parent Selector?

& is a special selector invented by Sass. Inside a nested rule it means “the outer selector.” When Sass compiles, it replaces & with that outer selector instead of applying normal nesting.

  • Add a pseudo-class: &:hover.alert:hover
  • Style the parent in a context: [dir=rtl] &[dir=rtl] .alert
  • Pass the parent into a pseudo-class: :not(&):not(.alert)
  • Append BEM pieces: &__copy.accordion__copy
💡
Beginner tip

Normal nesting (.alert { .icon { } }) becomes .alert .icon (descendant). Using & lets you glue selectors together or put the parent somewhere other than the front.

📝 Basic Syntax

styles.scss
.alert {
  // Pseudo-class on the outer selector
  &:hover {
    font-weight: bold;
  }

  // Outer selector in a certain context
  [dir=rtl] & {
    margin-left: 0;
    margin-right: 10px;
  }

  // Parent as an argument to a pseudo-class
  :not(&) {
    opacity: 0.8;
  }
}
⚠️
Heads up — placement

Because & might become a type selector like h1, it is only allowed where a type selector would be allowed—typically at the start of a compound selector. span& is invalid; use something like #{&}span only with care, or restructure the nest.

🏷️ Adding Suffixes

If the outer selector ends with an alphanumeric name (class, ID, or element), you can append extra text after &. This shines with BEM-style class names.

styles.scss
.accordion {
  &__copy {
    display: none;

    &--open {
      display: block;
    }
  }
}
// .accordion__copy / .accordion__copy--open

📄 Without Nesting

In Dart Sass 1.100.0+, you can write & { … } outside any nest. Sass emits a literal CSS & for the browser’s scoping root. You cannot append suffixes to a non-nested parent selector—there is nothing to suffix.

Older compilers (including Dart Sass 1.69.x used in many projects) still error with “Top-level selectors may not contain the parent selector &.” Prefer nested & until your toolchain upgrades.

🔢 & in SassScript

As a SassScript expression, & returns the current parent selector in the same shape selector functions use: a comma-separated list of space-separated lists of unquoted strings.

Outside any style rule, & is null (falsey). Mixins often use if(&, …, …) to behave differently when included at the root vs inside a rule.

💡
Advanced nesting

You can pass & to functions like selector.unify() and interpolate the result. Because Sass still auto-nests interpolated selectors, wrap with @at-root so the outer selector is not added twice.

⚡ Quick Reference

GoalCode
Hover / focus&:hover { … }
Parent in context.theme-dark & { … }
BEM element&__title { … }
BEM modifier&--active { … }
Not this selector:not(&) { … }
Detect nest in mixinif(&, '&.x', '.x')
Unify with type@at-root #{selector.unify(&, "input")}

Examples Gallery

Each example is verified with Dart Sass. Open View Compiled CSS for output.

📚 Getting Started

Replace the parent for pseudo-classes, context, and suffixes.

Example 1 — Pseudo-Classes, Context & :not(&)

Three classic parent-selector patterns in one rule.

styles.scss
.alert {
  &:hover {
    font-weight: bold;
  }

  [dir=rtl] & {
    margin-left: 0;
    margin-right: 10px;
  }

  :not(&) {
    opacity: 0.8;
  }
}

How It Works

&:hover glues the pseudo-class to .alert. [dir=rtl] & places the parent after another selector. :not(&) substitutes .alert as the argument.

Example 2 — BEM Suffixes with &__ and &--

Keep block, element, and modifier names next to each other in the source.

styles.scss
.accordion {
  max-width: 600px;
  margin: 4rem auto;
  width: 90%;
  font-family: "Raleway", sans-serif;
  background: #f4f4f4;

  &__copy {
    display: none;
    padding: 1rem 1.5rem 2rem 1.5rem;
    color: gray;
    line-height: 1.6;
    font-size: 14px;
    font-weight: 500;

    &--open {
      display: block;
    }
  }
}

How It Works

Text after & is appended to the parent class name. Nested &--open appends to .accordion__copy, not only .accordion.

📈 SassScript & Advanced Nesting

Inspect &, branch in mixins, and unify selectors.

Example 3 — & as a SassScript Value

Emit the current parent selector as a CSS value (for learning / debugging).

styles.scss
.main aside:hover,
.sidebar p {
  // & is a list of lists of unquoted strings
  parent-selector: &;
}

How It Works

Sass stringifies the parent selector list into the declaration value. Real stylesheets rarely need a custom property named parent-selector—this shows what & contains.

Example 4 — Mixin That Detects Nesting with if(&)

At the root emit .app-background; inside a rule emit &.app-background.

styles.scss
@mixin app-background($color) {
  #{if(&, '&.app-background', '.app-background')} {
    background-color: $color;
    color: rgba(#fff, 0.75);
  }
}

@include app-background(#036);

.sidebar {
  @include app-background(#c6538c);
}

How It Works

Outside a rule, & is null, so the mixin builds .app-background. Inside .sidebar, & is truthy, so it builds &.app-background.sidebar.app-background.

Example 5 — selector.unify with @at-root

Combine the outer selector with a type selector without double-nesting.

styles.scss
@use "sass:selector";

@mixin unify-parent($child) {
  @at-root #{selector.unify(&, $child)} {
    @content;
  }
}

.wrapper .field {
  @include unify-parent("input") {
    border: 1px solid #ccc;
  }
  @include unify-parent("select") {
    border: 1px solid #999;
  }
}

How It Works

selector.unify(&, "input") merges .wrapper .field with input into .wrapper input.field. @at-root prevents Sass from nesting that result under .wrapper .field again.

🚀 Real-World Use Cases

  • Component states&:hover, &:focus-visible, &[disabled].
  • BEM / ITCSS naming — keep __element and --modifier next to the block.
  • Theme / RTL overrides.theme-dark & or [dir=rtl] &.
  • Smart mixins — branch on if(&) for root vs nested includes.
  • Selector mathselector.unify / selector.append with @at-root.

🧠 How Compilation Works

1

Find a nested rule

Remember the outer selector as the current parent.

Nest
2

Replace &

Substitute the parent (or evaluate & in SassScript).

Replace
3

Honor @at-root

Skip auto-wrapping when you already built the full selector.

Control
4

Emit flat CSS

Output selectors browsers understand—no nested & left.

⚠️ Common Pitfalls

  • span& — invalid placement; & must start the compound selector.
  • Forgetting @at-root — interpolated & still gets nested again.
  • Suffix on complex parents — appending text only works when the outer ends in a simple name.
  • Top-level & on old Sass — needs Dart Sass 1.100+; errors on 1.69.x.
  • Assuming & outside rules is "" — it is null, not an empty string.

💡 Best Practices

✅ Do

  • Use &:hover / &:focus-visible for states
  • Keep BEM suffixes next to the block with &__ / &--
  • Branch mixins with if(&, …, …)
  • Pair selector functions with @at-root
  • Prefer readable nests over deep, clever selector math

❌ Don’t

  • Write invalid compounds like span&
  • Nest so deeply that the CSS specificity explodes
  • Rely on top-level & without checking your Sass version
  • Interpolate & without understanding auto-nesting
  • Use & where plain nesting already says what you mean

Key Takeaways

🔗 01

& = parent

outer selector

Core
👆 02

&:hover

glue states

States
🏷️ 03

&__ / &--

BEM suffixes

Naming
🔢 04

if(&)

mixin detect

Script
⚖️ 05

@at-root

with unify

Advanced

❓ Frequently Asked Questions

The ampersand & is a special selector that refers to the outer (parent) selector inside a nested rule. Sass replaces & with that outer selector instead of using normal nesting.
Nest &:hover { ... } inside the parent rule. .button { &:hover { opacity: 0.9; } } compiles to .button:hover { opacity: 0.9; }.
If the outer selector ends with a class, ID, or element name, you can append text: &__element and &--modifier become .block__element and .block__element--modifier.
Yes for context. [dir=rtl] & becomes [dir=rtl] .alert. But span& is not allowed—& must start a compound selector where a type selector would be allowed.
As an expression, & returns the current parent selector as a list of lists of unquoted strings. Outside any style rule it returns null, which is useful to detect whether a mixin was included inside a rule.
When you interpolate &, Sass still nests the outer selector automatically. @at-root tells Sass not to wrap again, so advanced selector math stays correct.
Did you know?

Official Sass docs sometimes show a typo like if(sass(&): …) in mixin examples. The correct check is simply if(&, …, …)—because & is already a SassScript expression.

Conclusion

The parent selector & turns nested Sass into precise CSS: glue states, append BEM names, flip parent context, and drive mixin logic. Start with &:hover, then grow into SassScript and selector functions when you need them.

Continue with Sass Placeholder Selectors or @at-root.

Next: Placeholder Selectors

Share silent % styles with @extend—no unused CSS.

Placeholder 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