DEV Community

Sarah Chima
Sarah Chima

Posted on

Nesting in SASS

Remember nesting in HTML? The thing we do all the time when we put a <p> in a <div> and a <span> in the <p> like this?

    <body>
        <div>
            <p>
                <span></span>
            </p>
        <div>
    </body>
Enter fullscreen mode Exit fullscreen mode

I bet you do. SCSS allows us to nest CSS selectors in a similar manner. Nesting is a shortcut to creating CSS rules. So instead of writing so many lines of CSS just to be specific on the style we want to apply to an element, we simply nest it. Let's use an example. In CSS, we want to style the li of a particular sidebar in a certain way, here's how we will target it.

   #sidebar ul li {
      background-color: #F2F2F2;
      color: #404040;
    }
Enter fullscreen mode Exit fullscreen mode

Using nesting, we will simply do the following and get the same results.

   #sidebar {
       ul {
           li {
               background-color: #F2F2F2;
               color: #404040;
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

This is better organized and it is easier to see the hierarchy. It produces the same result. You can add properties to the selector itself and not just to the nested selectors.

   #sidebar {
        position: fixed;
        height: 100%;

        ul {
            list-style-type: none;
            padding: 0;

            li {
                background-color: #F2F2F2;
                color: #404040;
            }
        }
    } 
Enter fullscreen mode Exit fullscreen mode

This will compile to

    #sidebar {
        position: fixed;
        height: 100%; }
    #sidebar ul {
        list-style-type: none;
        padding: 0; }
    #sidebar ul li {
        background-color: #F2F2F2;
        color: #404040; }

Enter fullscreen mode Exit fullscreen mode

You can also nest media queries too.

     #sidebar {
        position: fixed;
        height: 100%;

        @media (max-width:768px) {
            left: -9999;
        }

        ul {
            list-style-type: none;
            padding: 0;
        }
    } 
Enter fullscreen mode Exit fullscreen mode

This will compile to

    #sidebar {
        position: fixed;
        height: 100%; }
    @media (max-width: 768px) {
        #sidebar {
            left: -9999; } }
    #sidebar ul {
        list-style-type: none;
        padding: 0; }
Enter fullscreen mode Exit fullscreen mode

We can even nest CSS properties.

   li {
       background: {
           image: url("image.jpg");
           position: fixed;
           }
       margin : {
           top: 1rem;
           left: 2rem;
           right: 1rem;
           }
      }

Enter fullscreen mode Exit fullscreen mode

This will compile to

    li {
        background-image: url("image.jpg");
        background-position: fixed;
        margin-top: 1rem;
        margin-left: 2rem;
        margin-right: 1rem; }
Enter fullscreen mode Exit fullscreen mode

Really, nesting makes life a whole more easier. Let's next consider how we can use the ampersand & to nest pseudo classes and elements and to place selectors side by side.

The Ampersand in Nesting
In Sass, & is a very useful feature in nesting. If you want the selectors to be attached without leaving any space in between, we have to use the ampersand. This is especially useful when we have to nest pseudo-classes and pseudo-elements. If you want understand what pseudo-classes and pseudo-elements are, you can read this post. & is also useful when we have to place classes side by side to select elements that have those classes. Let's use an example to understand this.

   .list {
       background-color: white;
       color: #404040;

       /* Pseudo-class */
       &:hover {
           background-color: blue; 
           color: white
       }

       /* Pseudo-element */
       &:before {
            content: "List ";
       }  

       /* Placing selectors side by side */
       &.active {
            border-left: 3px solid blue;
            color: blue;
       }
   }
Enter fullscreen mode Exit fullscreen mode

This will compile to

   .list {
       background-color: white;
       color: #404040; }

   .list:hover {
       background-color: blue;
       color: white; }

   .list:before {
       content: "List ";
       width: 30px; }

   .list.active {
       border-left: 3px solid blue;
       color: blue; }
Enter fullscreen mode Exit fullscreen mode

See how they are all joined side by side with no space between? That's the power of the &.

CAUTION!!!
Nesting is very useful and makes our CSS organized but we do not want to misuse it. One way we can misuse it is by over-nesting selectors. Look at an example of over-nesting.

    div {
       .sidebar{
            position: fixed;
            height:  100%;

            ul {
                list-style-type: none;
                padding: none;

                .list {
                    background-color: white;
                    color: black;

                    a {
                        text-decoration: none;
                        i{
                           &:hover {
                                background:  transparent;
                            }
                        }
                    }
                }
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

This will compile to

   div .sidebar {
       position: fixed;
       height: 100%; }
   div .sidebar ul {
       list-style-type: none;
       padding: none; }
   div .sidebar ul .list {
       background-color: white;
       color: black; }
   div .sidebar ul .list a {
       text-decoration: none; }
   div .sidebar ul .list a i:hover {
          background: transparent; }

Enter fullscreen mode Exit fullscreen mode

Look at the last selector, that's six levels of nesting. That's so much. There's a lot of things wrong with this.

  1. Increase in file size: Look at the amount of code it added to the CSS file. This in turn increases the size of your file and affects performance.
  2. Specificity issues: Being too specific is itself a problem. A style in a selector that is very specific will be difficult to be overridden by another selector.
  3. Maintainability: This is also a problem. A change in any of the selectors in the top level selectors affects the other selectors.
  4. Styles are also not so reusable.

A rule of the thumb is not to nest more than 4 levels. Less than four levels is preferable. Rather than so many levels of nesting, you can use it to name your selectors and still be specific. See an example below.

   .sidebar {
       position: fixed;
       height: 100%;

       &-list {
           background-color: white;

           &-link {
               text-decoration: none;
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

This will compile to

   .sidebar {
      position: fixed;
      height: 100%; }
   .sidebar-list {
      background-color: white; }
   .sidebar-list-link {
      text-decoration: none; }
Enter fullscreen mode Exit fullscreen mode

See how much better this is. We exploited the power of nesting and still kept our code maintainable and reusable. So the key is using nesting in a way that it doesn't affect performance and its maintainability.

And it's a wrap. Thank you for reading. :)
Got any question or addition? Leave a comment.

Top comments (11)

Collapse
 
satansdeer profile image
Maksim Ivanov • Edited

Great tutorial, I like that you've also made a caution about the excessive nesting.

In my work I avoid styling elements by #id's. Usually I use them only as anchors.

Also a quick note about naming. For example you've used .sidebar-list-link.

I prefer to avoid this kind of "nesting" in naming as well and use only one level of nesting. So I would do .sidebar and .sidebar-list. And .list maybe with .for-sidebar modifier with .list-link. Basically I would follow a bit modified version of BEM methodology.

Collapse
 
sarah_chima profile image
Sarah Chima

Thanks for the addition. 😊😊

Collapse
 
lynnewritescode profile image
Lynne Finnigan • Edited

Great article! Another use for the ampersand that people might find useful would be to reference parent selectors with the ampersand at the end.

h1 {
    .parent-selector & {
        *insert styles*
    }
}

Very powerful!

Collapse
 
sarah_chima profile image
Sarah Chima

Awesome!!! Thanks for sharing this Lynne.

Collapse
 
aurelkurtula profile image
aurel kurtula • Edited

Great tutorial. A fantastic tip on this:

   .sidebar {
       position: fixed;
       height: 100%;

       &-list {
           background-color: white;

           &-link {
               text-decoration: none;
            }
        }
    }

Never thought about doing that.

Collapse
 
sarah_chima profile image
Sarah Chima

Thank you😊

Collapse
 
rhymes profile image
rhymes

Well explained.

Just an addition: I've been using stylelint and stylelint-config-sass-guidelines to keep my SASS files in check and you can also configure it to set a maximum nesting depth.

Collapse
 
sarah_chima profile image
Sarah Chima

That's awesome. I'll look at them. Thanks for sharing.

Collapse
 
jehdiaizon profile image
Jehdi Aizon

what does the & do when it is before or after a nested class or id??

Collapse
 
bethberry profile image
BethBerry

Nesting with SASS does not seem to work for me? banishing negativity spells

Collapse
 
isabelsinclair profile image
IsabelSinclair

Should you nest everything in SASS? comment rendre un homme amoureux