Skip to content

Sass Nesting — Complete Guide

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Sass Nesting. We cover key concepts, practical examples, and best practices to help you master this topic.

Sass nesting mirrors HTML structure by placing child selectors inside parent rules using the & parent selector for cleaner, more maintainable stylesheets.

What You'll Learn

  • Basic nesting of selectors
  • The & parent selector
  • Nesting with pseudo-classes and pseudo-elements
  • BEM naming with nesting
  • Media query nesting
  • Best practices for nesting depth

Why It Matters

  • Nesting reduces repetition of parent selectors
  • Mirrors HTML structure for readability
  • Groups related styles logically
  • Prevents selector typos and omissions

Real-World Use

  • A component stylesheet nests all related selectors
  • A nav component nests :hover, :focus, and child items
  • BEM blocks use nesting for elements and modifiers
  • Media queries are nested inside component rules
flowchart LR
  A[Sass Nesting] --> B[Parent Selector]
  A --> C[Child Selectors]
  A --> D[Pseudo-classes]
  A --> E[Media Queries]
  B --> F[&:hover, &__element]
  C --> G[.parent > .child]
  D --> H[&::before, &:focus]

Nesting Patterns

Code Example: Basic Nesting

// Without nesting (CSS)
.nav { background: #333; }
.nav ul { list-style: none; margin: 0; }
.nav li { display: inline-block; }
.nav a { color: white; text-decoration: none; }
.nav a:hover { text-decoration: underline; }

// With nesting (SCSS)
.nav {
    background: #333;

    ul {
        list-style: none;
        margin: 0;
    }

    li {
        display: inline-block;
    }

    a {
        color: white;
        text-decoration: none;

        &:hover {
            text-decoration: underline;
        }
    }
}

Expected output: Both compile to the same CSS. The nested version groups .nav styles together and shows the HTML structure visually.

Code Example: The & Parent Selector

// & refers to the parent selector
.button {
    padding: 0.75rem 1.5rem;
    background: #0066CC;
    color: #fff;
    border: none;
    border-radius: 4px;

    // Pseudo-classes
    &:hover {
        background: darken(#0066CC, 10%);
    }

    &:focus-visible {
        outline: 3px solid #0066CC;
        outline-offset: 2px;
    }

    &:active {
        transform: scale(0.98);
    }

    // Pseudo-elements
    &::before {
        content: '→ ';
    }

    // Adjacent sibling
    & + & {
        margin-left: 0.5rem;
    }

    // Modifier classes
    &-large {
        padding: 1rem 2rem;
        font-size: 1.25rem;
    }

    &-small {
        padding: 0.5rem 1rem;
        font-size: 0.875rem;
    }

    // State classes
    &.is-loading {
        opacity: 0.7;
        pointer-events: none;
    }

    &.is-disabled {
        background: #ccc;
        cursor: not-allowed;
    }
}

// Parent selector at the end
.nav-item {
    .nav-header & {
        font-weight: bold;
    }
}
// Compiles to: .nav-header .nav-item { font-weight: bold; }

Expected output: The & selector creates compound selectors (.button-large, .button.is-loading) and pseudo-classes (.button:hover). It can appear at the beginning, middle, or end of the selector.

Code Example: BEM with Nesting

// BEM (Block Element Modifier) with nesting
.card {
    $block: &;  // Store parent reference

    background: #fff;
    border: 1px solid #eee;
    border-radius: 8px;
    overflow: hidden;

    // Element
    &__image {
        width: 100%;
        height: auto;
    }

    &__body {
        padding: 1.5rem;
    }

    &__title {
        font-size: 1.25rem;
        margin: 0 0 0.5rem;
    }

    &__text {
        color: #666;
        line-height: 1.6;
    }

    // Modifier
    &--featured {
        border-color: #0066CC;
        box-shadow: 0 4px 12px rgba(0, 102, 204, 0.15);
    }

    &--compact {
        #{$block}__body {
            padding: 1rem;
        }
        #{$block}__title {
            font-size: 1rem;
        }
    }

    // Conditional styling within modifier
    &--dark {
        background: #333;
        color: #fff;

        #{$block}__text {
            color: #ccc;
        }

        #{$block}__title {
            color: #fff;
        }
    }
}

Expected output: BEM nesting keeps the card block self-contained. The $block variable stores the parent selector for use in nested modifiers. All card elements are clearly namespaced under .card.

Code Example: Nesting Media Queries

// Media queries nested inside selectors
.card {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    padding: 1rem;

    @media (min-width: 768px) {
        grid-template-columns: 200px 1fr;
        padding: 2rem;
    }

    @media (min-width: 1024px) {
        grid-template-columns: 250px 1fr;
        padding: 3rem;
    }
}

// Nested media queries compile to:
// .card { ... }
// @media (min-width: 768px) { .card { ... } }
// @media (min-width: 1024px) { .card { ... } }

// Multiple conditions
.component {
    font-size: 1rem;

    @media (min-width: 768px) and (hover: hover) {
        font-size: 1.125rem;

        &:hover {
            transform: scale(1.02);
        }
    }
}

Expected output: Media queries are colocated with the component they affect. Sass extracts them to the appropriate position in the compiled CSS. This makes component files self-contained.

Common Mistakes

  1. Nesting more than 3-4 levels deep — .header .nav .list .item a creates overly specific selectors that are hard to override.
  2. Using & to create unexpected selectors — &.class compiles to .parent.class (no space), while & .class (with space) compiles to .parent .class.
  3. Nesting media queries too deeply — Nested media queries in deeply nested selectors create repeated, complex output. Keep nesting shallow.
  4. Overusing BEM with nesting — Deep BEM nesting (block__element--modifier) can create long selectors. Interpolation with $block reduces repetition.
  5. Not using & for adjacent siblings — & + & is cleaner than repeating the class name. It compiles to .button + .button.
  6. Forgetting that nesting adds specificity — .nav a has specificity 0,1,1. Nested versions have the same specificity, but deeper nesting increases it.
  7. Mixing tabs and spaces — Sass indentation (for .sass syntax) requires consistency. SCSS is more forgiving with braces.

Practice Questions

  1. What does the & symbol represent in Sass nesting? The parent selector. It refers to the outer selector and allows appending pseudo-classes and modifiers.
  2. What is the recommended maximum nesting depth? 3-4 levels. Deeper nesting creates overly specific selectors and fragile output.
  3. How do you create a BEM element with nesting? Use &__element for elements and &--modifier for modifiers inside the block.
  4. Can media queries be nested inside selectors? Yes. Sass allows @media rules to be nested inside selectors for component colocation.

FAQ

Does nesting affect CSS performance?

No. Nesting affects only the authoring experience. The compiled CSS has the same performance as hand-written CSS.

Should I nest everything?

No. Only nest when it mirrors the HTML structure and improves readability. Flat selectors are easier to override.

What is the @at-root directive?

@at-root moves styles outside of the parent selector. Useful when you need to break out of nesting to output at the root level.

Mini Project

Build a complete media object component (image + content side by side) using Sass nesting with BEM. Include: .media block, __image element, __body element, __title element, __text element, --reverse modifier (image on right), --center modifier (vertically centered), and --featured modifier. Nest pseudo-classes (:hover) and pseudo-elements (::before for quotes). Nest media queries for responsive breakpoints (stack on mobile). Ensure nesting depth does not exceed 3 levels.

What's Next

Continue with Lesson 5: Sass Mixins to learn reusable style blocks with mixins.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro