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
Concept
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.
Foundation
📝 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.
BEM & Naming
🏷️ 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.
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.
Expressions
🔢 & 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.
Cheat Sheet
⚡ Quick Reference
Goal
Code
Hover / focus
&:hover { … }
Parent in context
.theme-dark & { … }
BEM element
&__title { … }
BEM modifier
&--active { … }
Not this selector
:not(&) { … }
Detect nest in mixin
if(&, '&.x', '.x')
Unify with type
@at-root #{selector.unify(&, "input")}
Hands-On
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.
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.
selector.unify(&, "input") merges .wrapper .field with input into .wrapper input.field. @at-root prevents Sass from nesting that result under .wrapper .field again.
Applications
🚀 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 math — selector.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.
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.
Pro Tips
💡 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
Summary
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.
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.
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.