The Pros and Cons of Nesting Your Sass Code

Nesting can be a good way to organize your Sass code. It can also lead to specificity problems if you nest too deeply. You don’t have to look to far to find people who’ll tell you how wonderful nesting is or how the universe might cave in on itself if you attempt to nest your code.

The truth as usual is somewhere in between the extremes.

Bird's nest built on power lines

Last week I showed you how to nest your Sass code and throughout the post I mentioned you have to be careful not to nest too many levels deep. I also mentioned how nested Sass can help organize your code.

Today I want to talk about both. I want to show you the good and bad of nesting and hopefully leave you with the understanding that nesting as fine as long as you do it responsibly.

Let’s start with the cons, because I think they’re easier to explain and understand.

The Cons of Nested Sass

There’s nothing specifically wrong with nesting, but you can run into problems if you nest your code too many levels deep.

For example say you have the following HTML and you want to style the link.

1
2
3
4
5
6
7
<main>  
  <div class="one">  
    <p class="two">Some text  
      <a href=""></a>  
    </p>  
  </div>  
</main>

You probably know that a selector like main .one .two a is overly specific. The link you’d style in the selector is tightly coupled to a specific HTML structure, which is generally something to avoid.

However, if you nest your Sass you could be fooled into thinking your selector isn’t specific at all

1
2
3
4
5
6
7
main {  
 .one {  
   .two {  
     a {color: red}  
   }
 }  
}

The Sass makes it appear as though you just styled a simple link, but once the Sass is compiled you end up with the same overly specific selector we saw without the nested Sass.

One problem with overly specific selectors is you have to write even more specific selectors to override them for that one case where you want an element to look different or your styles fall apart when you decide that an element inside one area of your design should be moved to another area of your design.

While I agree that nesting too many levels deep should be avoided, I don’t think that makes nesting a bad thing or something to be avoided. True, it’s easy to get carried away and end up with some very specific selectors, but it’s just as easy to get carried away writing very specific selectors in CSS.

I’ll paraphrase the title of an article by Roy Tomeij and say that nested Sass doesn’t create bad code. Bad coders do. Yes it’s easy to nest too many levels deep. The solution is easy. Don’t do it. There’s nothing forcing you to have deeply nested Sass code and once you understand you shouldn’t, it’s not that hard to avoid.

Most every other argument against nested Sass that I’ve come across is a variation of this one in the sense that the downside is a potential problem that isn’t too hard to avoid if you follow best practices and try to write good code in general.

Mario Ricalde came up with the inception rule of limiting yourself to four levels of nesting, which makes my example above perfectly fine.

I try to aim for no more than three levels of nesting, which is about as much as I’m willing to chain selectors. In fact I try to keep nesting to two levels most of the time, only using three levels when I think it’s necessary.

A good rule to follow is to nest only as deep as you’re willing to chain selectors.

The Pros of Nesting

The cons might be avoidable, but what are the benefits of nested Sass? For me, the benefits are more readable and maintainable code.

For example here’s some generic HTML that I commonly use when building menus and navigation bars. It’s an unordered list with a class of global-navigation and inside are list items that contain links.

1
2
3
4
5
6
<ul class="global-navigation">  
 <li><a href=""></a</li>  
 <li><a href=""></a</li>  
 <li><a href=""></a</li>  
 <li><a href=""></a</li>  
</il>

Here’s how I might organize the Sass.

1
2
3
4
5
6
7
8
9
10
11
12
13
.global-navigation {  
 styles here

 li {  
   styles here  
 }

 a {  
   styles here

   &:hover {styles here}  
 }
}

I use the class name as the parent selector and I nest styles for both the list items and the links. Notice that I didn’t nest the link inside the list item here to keep from nesting too deeply.

I find a block of code like this easy to read and it keeps all the code for the global navigation in one place. It saves some typing in that I don’t have to repeat .global-navigation in front of the other selectors too.

In the early days of Sass some thought that nesting your Sass with the same hierarchy as your HTML was a nice way to visualize your HTML in your Sass file, but that tends to lead to too much nesting and overly specific selectors.

The code above for a navigation bar isn’t too deeply nested, saves some typing, and I find it generally easy to read. It also compiles to how I would have written the selectors as CSS before I knew about preprocessors.

1
2
3
4
.global-navigation {}  
.global-navigation li {}  
.global-navigation a {}  
.global-navigation a:hover {}

BEM, SMACSS and Sass

If you prefer to write CSS using BEM or SMACSS, you have another reason to like nested Sass. Last week I mentioned how you could use an ampersand to refer to the parent selector and it works well with the naming conventions used by BEM and SMACSS.

I don’t want to get too into the details of either here, but they both make use of naming conventions to write more modular CSS. For example you might write BEM with the following conventions.

1
2
3
.block {}  
.block__element {}  
.block__element--modifier {}

For a form and submit button that might look like the following:

1
2
3
.form {}  
.form__submit {}  
.form__submit--disabled {}

Using the ampersand as a parent reference you could write your Sass like this:

1
2
3
4
5
.form {  
    &__submit {  
      &--disabled { }  
    }
}

The second & (&–disabled) references its parent, which is .form__submit once the reference is replaced with the parent selector. The code will compile to:

1
2
3
.form {}  
.form__submit {}  
.form__submit--disabled {}

SMACSS uses a different naming convention, but you could similarly use the ampersand to nest your code if you’re working with SMACSS.

Closing Thoughts

I prefer nesting because it helps me organize my code in a way that’s more readable to me. Just be aware you can make a mess of Sass as easily as you can make a mess of CSS.

Most of the downsides of nested Sass come about from nesting too many levels deep. The downsides are more to do with poor coding than nesting in general. If you keep from nesting more than two or three levels deep, you should be ok.

Next week, I’ll talk about another feature you’re likely to use soon after you start working with Sass. I’ll talk about using variables in Sass, which happens to be one of my favorite features of CSS preprocessors.

Download a free sample from my book, Design Fundamentals.

2 comments

  1. .form {
    &__submit {
    &–disabled { }
    }
    }

    That’s exactly what every pro avoids.

    Searching through large scale Sass files for like form__submit is impossible with this syntax. And it breaks your statement of “advoid massive nesting”

    • And by pro you mean you and by every you mean the handful of people you’ve worked with. If you search “sass nesting BEM” you’ll find more than one professional developer recommending the same thing I did.

      I never said to avoid massive nesting. I said you probably don’t want to nest too many levels deep. I don’t think 2 or 3 levels is too many nor would it be considered massive.

Leave a Reply

Your email address will not be published. Required fields are marked *