Sass selector.nest() Function

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

What You’ll Learn

selector.nest() belongs to the built-in sass:selector module. It combines selectors as if you nested them in a stylesheet—usually with a descendant space, or with & for compounds and BEM. This page covers lists, vs selector.append, and five compiled examples.

01

Concept

Nest like SCSS

02

Module

@use "sass:selector"

03

Returns

Selector value

04

Args

$selectors...

05

Parent &

Allowed after first

06

Practice

5 examples

What Is selector.nest()?

Official docs: combines $selectors as though they were nested within one another in the stylesheet. Without &, that usually means a descendant combinator (a space): ul li, not ulli.

  • Takes one or more selector arguments ($selectors...).
  • Placeholder selectors are allowed.
  • Unlike most selector functions, every argument except the first may contain parent selectors (&).
  • See also selector.append() when you want no space between pieces.
💡
Beginner tip

Picture writing nested SCSS, then flattening it with a function. nest(".alert", "&:hover") is the same idea as nesting &:hover inside .alert.

📝 Syntax

styles.scss
@use "sass:selector";

// Recommended
selector.nest($selectors...)

// Legacy global name
selector-nest($selectors...)

Parameters

ParameterTypeRequiredDescription
$selectors...SelectorsYes (one or more)Selectors to nest. Later args may include &; the first usually should not.

Return value

TypeResult
SelectorA nested selector (often usable inside #{…})

📦 Loading sass:selector

styles.scss
// Recommended — namespaced (Dart Sass 1.23+)
@use "sass:selector";
$sel: selector.nest("ul", "li"); // ul li

// Optional — bring members into scope
@use "sass:selector" as *;
$sel: nest(".alert", "&:hover"); // .alert:hover

// Legacy global
$sel: selector-nest("ul", "li");

🎨 Official Patterns

CallResult
nest("ul", "li")ul li
nest(".alert, .warning", "p").alert p, .warning p
nest(".alert", "&:hover").alert:hover
nest(".accordion", "&__copy").accordion__copy

The last two show why & matters: without it, nesting would insert a space; with it, you get compounds and BEM-style names—the same way nested SCSS works.

⚖️ nest vs append

HelperTypical resultUse when
selector.nest.alert .warn or .alert:hover with &Nested stylesheet behavior / parent selectors
selector.append.alert.warn (no space; no &)Same element / glue without nesting rules

For BEM, both can produce .block__el: nest with &__el, or append with __el. Prefer the style that matches how you think about nesting.

🛠 Compatibility

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

Implementationnest
Dart SassYes — prefer selector.nest (module since 1.23.0)
LibSassLegacy selector-nest may exist; no @use "sass:selector"
Ruby SassLegacy selector-nest 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";
Descendantselector.nest("ul", "li")
List parentselector.nest(".a, .b", "p")
Pseudo with &selector.nest(".alert", "&:hover")
BEM with &selector.nest(".block", "&__el")
No space / no &selector.append(…) instead

Examples Gallery

Each example uses selector.nest 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 Nest Samples

Descendants, lists, &:hover, and BEM with &.

styles.scss
@use "sass:selector";

.probe {
  --ul: #{selector.nest("ul", "li")};
  --alert: #{selector.nest(".alert, .warning", "p")};
  --hover: #{selector.nest(".alert", "&:hover")};
  --bem: #{selector.nest(".accordion", "&__copy")};
}

How It Works

Without &, Sass inserts nesting spaces. With &, the parent is substituted just like nested SCSS.

Example 2 — Build Rule Selectors

Interpolate nested results into real style rules.

styles.scss
@use "sass:selector";

#{selector.nest(".card", ".title")} {
  font-weight: 700;
}

#{selector.nest(".card, .panel", "p")} {
  margin: 0;
}

How It Works

The second call expands the parent list the same way nested SCSS would under .card, .panel.

📈 Practical Patterns

Mixins, append contrast, and parent-selector loops.

Example 3 — State Mixin with &

Nest a pseudo onto a base selector using the parent reference.

styles.scss
@use "sass:selector";

@mixin state($base, $pseudo) {
  #{selector.nest($base, $pseudo)} {
    outline: 2px solid currentColor;
  }
}

@include state(".btn", "&:hover");
@include state("a", "&:focus-visible");

How It Works

Passing &:hover (not :hover alone) keeps the compound on the same element instead of creating a descendant.

Example 4 — Nest vs Append Side by Side

Same pieces, different nesting rules.

styles.scss
@use "sass:selector";

.compare {
  --nest: #{selector.nest(".alert", ".warn")};
  --append: #{selector.append(".alert", ".warn")};
  --bem-nest: #{selector.nest(".menu", "&__item")};
  --bem-append: #{selector.append(".menu", "__item")};
}

How It Works

Plain class nesting inserts a space; append does not. With BEM, nest needs &__item while append uses __item—both can land on .menu__item.

Example 5 — Parent Selector Loop

Build several nested pieces from one block name.

styles.scss
@use "sass:selector";

$block: ".nav";
$parts: "&__link", "&__icon", "&:hover";

@each $part in $parts {
  #{selector.nest($block, $part)} {
    display: inline-block;
  }
}

How It Works

Each loop item includes &, so results stay compounds on .nav—elements and a hover state in one pass.

🚀 Real-World Use Cases

  • Programmatic nesting — build descendant selectors from string parts in mixins.
  • State helpers — nest &:hover, &:focus-visible, or &.is-open.
  • BEM tooling — nest &__el / &--mod onto a block name.
  • List expansion — nest children under comma-separated parents in one call.
  • Design-system APIs — accept a base selector and return nested variants at compile time.

🧠 How Compilation Works

1

Pass nested pieces

Call selector.nest(".card", ".title") or use &.

Source
2

Sass nests them

Applies the same rules as nested SCSS, including parent substitution.

Compile
3

Interpolate into rules

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

Emit
4

CSS ships

Browsers only see finished selectors like .card .title or .btn:hover.

⚠️ Common Pitfalls

  • Expecting no space — without &, nest usually inserts a descendant space; use append or &.
  • Putting & in the first argument — parent selectors belong in later arguments.
  • Passing :hover without & — that nests as a descendant, not a compound.
  • Forgetting interpolation — wrap results in #{…} to use them as rule selectors.
  • Old compilers without modules — use Dart Sass 1.23+ for @use "sass:selector".

💡 Best Practices

✅ Do

  • Use @use "sass:selector" and selector.nest()
  • Use & for compounds, pseudos, and BEM on the same element
  • Use nest for descendant / nested-stylesheet behavior
  • Prefer append when you want glue with no nesting rules
  • Prefer Dart Sass 1.23+

❌ Don’t

  • Assume every nest call inserts a space—check for &
  • Put parent selectors in the first argument
  • Confuse nest with string concatenation
  • Expect browsers to evaluate the call
  • Rely on LibSass for the module API

Key Takeaways

Knowledge Unlocked

Five things to remember about selector.nest()

Combine selectors like nested SCSS—spaces by default, & when you need compounds.

5
Core concepts
📦 02

Module

sass:selector

@use
🔗 03

Default

descendant space

Output
📚 04

Parent

& after first arg

Detail
05

Alt

append for no space

Compare

❓ Frequently Asked Questions

selector.nest($selectors...) combines selectors as though they were nested within one another in the stylesheet. Example: nest("ul", "li") becomes ul li.
nest follows nesting rules (often a descendant space, or & for compounds). append glues pieces with no space: append(".alert", ".warn") is .alert.warn, while nest(".alert", ".warn") is .alert .warn.
Yes for every argument except the first. Official docs: unlike other selector functions, all of them except the first may also contain parent selectors. Example: nest(".alert", "&:hover") becomes .alert:hover.
Nesting expands across lists like nested SCSS. nest(".alert, .warning", "p") becomes .alert p, .warning p.
Yes. selector-nest($selectors...) is the legacy global name. Prefer selector.nest 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 call out that selector.nest is special: it is one of the few selector helpers that allows parent selectors—on every argument except the first.

Conclusion

selector.nest() combines selectors like nested SCSS: descendants by default, compounds and BEM when you pass & after the first argument. Reach for selector.append when you want glue without nesting rules.

Continue with selector.parse() or the Sass introduction.

Next: parse selectors

Learn selector.parse() to convert selector strings into Sass lists.

selector.parse() →

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