Use nesting with SASS

Using selectors inside of selectors

Just as you nest Ā <li>s within an Ā <ul>Ā  in HTML, you can nest their selectors within Sass:

ul {
    list-style: none;
    text-align: right;
    li {
        display: inline;
        font-size: 3rem;
        color: #D6FFF5;
    }
}

Now that you have a clear hierarchy of the selectors reflecting their HTML structure, your Ā <li>sĀ  are nested within theĀ <ul>, just like they would be in HTML.

Rather than having to scroll through a CSS file looking for individual selectors and their rule sets, you can go to a single spot in the file and see how Ā <ul>s and their childĀ <li>Ā are styled. That means you only have to go to one location to make updates in the future.

Cleaner? Check. āœ… Maintainable? Check. āœ…

Take a look at the resulting CSS:


ul {
    list-style: none;
    text-align: right;
}

ul li {
    display: inline;
    font-size: 3rem;
    color: #D6FFF5;
}

The Ā <ul>Ā  received all of the rules assigned outside of the nested selector. And the Ā <li>Ā  received the rules that were assigned within its nested selector. Notice that the Ā <li>Ā  isn’t a singular element selector. Instead, we’ve created a descendant combinator.

Try it out for yourself!

Let’s give our CSS some structure and put our new-found nesting knowledge to use.Ā In this interactive exercise, we have a Ā .parentĀ  selector, and a Ā .childĀ  selector. Let’s organize them to reflect their relationship using Sass’ nesting by placing the Ā .childĀ  rule set within the Ā .parentĀ  rule set.

Nest theĀ .childĀ selector and its contents withinĀ .parent

Once you've tried it yourself, check your work in this CodePen!

We’ve performed the most basic form of nesting within Sass, which is placing a selector within another selector. Sass will always compile this as selectors separated by spaces, which, in CSS, is a descendant combinator.

Other types of combinators

If you can create descendant combinators, it stands to reason that you can create other combinators as well! In fact, you can create any of the otherĀ CSS combinators:

.parent {
    background-color: #15DEA5;
}

.parent .descendant {
    color: #fff;
}

.parent > .child {
    color: #D6FFF5;
}

.parent + .adjacent {
    color: #001534;
}

You remember these, right? Let's do a little recap:

  1. In the first case, anythingĀ relatedĀ to the parent element will take on the designated background color.Ā 

  2. In the second case, if the second element is theĀ descendantĀ of the first element, then it will have the specified color.Ā 

  3. In the third case, if the second element is aĀ childĀ of the first element, it'll have the designated color.Ā 

  4. In the fourth case, if the second element is immediatelyĀ precededĀ by the first, it'll have the supplied color.Ā 

Wait, what's the difference between "descendant" and "child"?Ā 

It's actually the same as in plain English:

  • You are both theĀ childĀ and theĀ descendantĀ of your parents.Ā 

  • You aren't the child of your grandparents, but you are theirĀ descendant.Ā 

A child element, therefore, has a direct and immediate link to the parent element.

By adding the appropriate combinator symbol before a nested selector, you can create any of theĀ CSS combinators in Sass:

.parent {
    background-color: #15DEA5;
    .descendant {
        color: #fff;
    }
    >.child {
        color: #D6FFF5;
    }
    +.adjacent {
        color: #001534;
    }
}

When you nest a block in Sass, it creates an individual CSS selector with the parent selector appended, separated by the appropriate combinator.

Try it out for yourself!

It’s time to get all familial and whatnot as we create selectors that style based on their relationship to the root selector. The code base already contains a selector for the ā€œrootā€ class. Let’s use nesting and combinators to style the elements surrounding and within the Ā .rootĀ  element in the HTML file.

  • Nest a selector for the Ā .generalĀ  class using the general sibling combinator ( Ā ~Ā  ) and assign it a background colorĀ of your choosing

  • Nest a selector for the Ā .adjacentĀ  class using the adjacent sibling combinator ( Ā +Ā  ) and assign it a background color of your choosing

  • Nest a selector for the Ā .childĀ  class using the child combinator ( Ā >Ā  ) and assign it a background color of your choosing.

  • Nest a selector for the Ā .descendantĀ  class using the descendant.

  • Normally the descendant combinator is a space ā€œā€, but with Sass, directly nesting a selector will compile as the space of the descendant combinator in the CSS.

  • Assign the nested Ā .descendantĀ  selector a background color of your choosing.

Review the resulting rendered HTML in the browser pane andĀ compare your answer to mine with this CodePen.

But what if we don’t want a separation between the parent and child?

To do that, you'll harness the power of the ampersand!

Enter the ampersand

You need to add a Ā li:hoverĀ  pseudo-class to your Ā <li>s to provide visual feedback and better the user experience. So, let’s nest the pseudo-selector within ourĀ liĀ selector:

ul {

    list-style: none;
    text-align: right;
        li {
            display: inline;
            font-size: 3rem;
            color: #D6FFF5;
            :hover {
                color: #001534;
            }
        }
}

Which compiles to:

ul {
    list-style: none;
    text-align: right;
}
ul li {
    display: inline;
    font-size: 3rem;
    color: #D6FFF5;
}
ul li :hover {
    color: #001534;
}

Well, that won't work… šŸ˜• Remember that nesting in Sass creates combinators. But you don’t want a combinator before your pseudo-selector. That’s not how they work; you need it to beĀ immediately joined to their selectorĀ to have the desired effect.

Sass has a special character to concatenate the parent and child selectors: theĀ ampersand (&)!Ā Prefixing a nested selector with an ampersand will directly join it to the parent selector without any combinators.

So, let’s add an ampersand before our Ā :hoverĀ  pseudo-selector:

ul {
    list-style: none;
    text-align: right;
        li {
            display: inline;
            font-size: 3rem;
            color: #D6FFF5;
            &:hover {
                color: #001534;
            }
        }
}

And check out the resulting CSS:

ul {
    list-style: none;
    text-align: right;
}
ul li {
    display: inline;
    font-size: 3rem;
    color: #D6FFF5;
}
ul li:hover {
    color: #001534;
}

Much better! Now we have a properly functioning hover state for our Ā <li>Ā s, all built within a single block of code.

Try it out for yourself!

Nesting in Sass is awesome, but sometimes we might want to nest a selector that doesn’t work any of the CSS combinators, such as pseudo-selectors likeĀ :hoverĀ andĀ :focus. For times like those, we want to use the ampersand ( & ) to join the name of the parent to child being nested. In this interactive exercise:

  • Nest aĀ :focusĀ selector within theĀ .inputĀ class selector

  • Add a new background color and font color to the theĀ :focusĀ selector

  • Check out the result by interacting with the text box in the browser pane

Think you've got it? Compare your solution to mine in this CodePen!

Nesting: a dab'll do ya

There’s no physical limit as to how deeply you can nest within Sass. It can be tempting to completely mirror your HTML within your Sass, creating a perfect replication of the hierarchy.

.parent-div {
    background-color: #15DEA5;
    .child-div {
        color: #fff;
        .grandchild-div {
            color: #D6FFF5;
        }
    }
}

But, remember, when you nest selectors, you increase the specificity of the compiled selectors. So, if you nest too deeply, you’ll end up with selectors of incredibly high specificity, making them extremely difficult to modify or override.

.parent-div {
    background-color: #15DEA5;
}
.parent-div .child-div {
    color: #fff;
}
.parent-div .child-div .grandchild-div {
    color: #D6FFF5;
}

Trying to override a selector as specific as Ā .parent-div .child-div .grandchild-divĀ  would require an even more specific selector. It also greatly hinders the re-usability of your code; unless you were to add an element later that exactly matches this hierarchy of classes, this selector is completely useless. This is brittle code that will be difficult to maintain. And that defeats the purpose of using a preprocessor at all!

Rather than trying to replicate the hierarchy of the HTML, it is better to write nested selectorsĀ only relative to the root selector.Ā It won’t represent the HTML structure as clearly, but it helps to ensure a low specificity in your codebase while maintaining flexibility and modularity.

Try it out for yourself!

Time to roll up your sleeves for another interactive exercise!

In this CodePen, move the nestedĀ .particleĀ selector up one level in the hierarchy, putting it on the same level as theĀ .atomĀ selector.

The rendered HTML should now look a bit different, with anotherĀ .particleĀ div showing up that wasn’t styled by the previously over-specificĀ .particleĀ selector.

Check your end result with this CodePen.

Nesting in Sass is an extremely powerful tool that helps you to group relevant selectors, creating a codebase that is easy to navigate and maintain. However, it does have the drawback of ballooning specificity. Now, you might be thinking back to BEM, and the organization and structure it helps impart on your selectors. You might alsoĀ recall that it’s built upon a foundation of low specificity. Which is at direct odds with the increase in specificity that comes from nesting. So, which should you use? BEM or nesting?

I would ask: why not have your cake and eat it too? šŸ° That's what we'll show you how to do in the next chapter. We’ll combine the power of Sass and the order of BEM to create flat selectors, while maintaining the structure of nesting.

Let's recap!

  • In Sass, selectors can be nested inside other selectors.

  • Sass can create any of the CSS combinators.

  • Use the ampersand to join a nested selector to a parent selector without using a combinator.Ā 

  • Be wary of creating overly specific selectors.Ā 

Ever considered an OpenClassrooms diploma?
  • Up to 100% of your training program funded
  • Flexible start date
  • Career-focused projects
  • Individual mentoring
Find the training program and funding option that suits you best