Nesting in LESS/SASS allows you to write descendant selectors in a syntax that is more natural and easier to read. It is one of the most basic and used feature of CSS preprocessors, yet, some believe it is being overused.

Lately I’ve read multiple articles that warn of the dangers of using nesting. In my experience however, nesting benefits outweigh the issues that were brought up. Here is why.

The benefits

Let’s go over the good stuff first.

Readability

Consider the following LESS:

What can be implied by looking at it? You know that there are 2 sections, main and sidebar and you know that each might have an advert inside and each has a header and a content. You also know that each advert is uniquely styled based on its section. Knowing all that, it would be very easy for you to match the HTML to the LESS file:

Once all the properties are written, it might be not as pretty to look at, but that’s what you have Code Folding for (in most editors and IDEs). You can always fold (collapse) it to get the same informative look.

Informative look even with multiple properties

Namespaces

Pretty and concise class names, as seen above, are an advantageous result of nesting. If the element you are specifying represents an advert, it should be called as such, e.g, advert.

What if you have 2 adverts in different places in the site? As shown above, with nesting it isn’t a problem since each advert has different ancestors. Without nesting, however, you would need to give each advert a different name, that describes its location, like so:

.app-sidebar { ... }

.app-sidebar-advert { ... }

.app-sidebar-advert-header { ... }

.app-sidebar-advert-content { ... }

Now instead of having a name that describes what the styling class is, you’re you’re describing its location. It is basically nesting, encoded in a string.

To my taste, this is awkward to read in LESS file and even more awkward to use in HTML.

Conflicts and unexpected results

When working with CSS, whenever I would change anything, I would have a gnawing fear “What else did I just muck up?”.

For example, if I saw that in my CSS:

.advert { width: 200px; height: 30px; }

I’d have no way of knowing what would happen if I changed it. It is possible it is used only at one specific place, but perhaps another developer decided to use it elsewhere. Now for each CSS change I am required to search the code and look where and how it is used.

Nesting, and specifically deep nesting, solves this issue — Every selector that is intended to be used in a specific place, can actually be used only there. If the resulting CSS selector is .app .sidebar .advert .header my life becomes easier as I know that this selector is only used in the header of sidebar advert.

Scope — Global, shared or specific

Nesting a selector makes a strong statement — This selector will only be used in this specific place. As far as any other HTML elements are concerned, this selector is private:

.app {

.sidebar {

.advert {

...

}

}

.sidebar {

.advert {

...

}

}

}

What happens if you want to share some characteristics between these adverts? Then you could use mixins (or extend):

.app {

.advert-shared() {

...

} .sidebar {

.advert {

.advert-shared();

...

}

}

.main{

.advert {

.advert-shared();

...

}

}

}

Now the common properties are shared and it’s clear which parts of the advert are unique to the sidebar and which are shared.

What if you wanted the advert to be styled the same in all the site? Then you can lose the nesting completely:

.advert-component {

...

} .app {

.sidebar {

...

}

.main {

...

}

}

By making this selector global, it can be used everywhere. Naturally with what was said above, it should be only done for components that are truly used in the whole site.

This flexibility allows you to make your LESS files clearer and have a structure that explains itself. You don’t need to search HTML to know the structure in which the class is used, since the LESS file itself is self-explanatory.

The downsides?

These are the downsides that were listed in the aforementioned articles.

Coupling of HTML and CSS

Consider the following LESS:

div.main {

& > div.sidebar {

& > div.advert {

...

}

}

}

That would match to the following HTML:

<div class="main">

<div class="sidebar">

<div class="advert">

</div>

</div>

</div>

If we change anything in the structure of the HTML however, the selector will no longer function. It would be enough to change the div to section to make it break.

To handle this issue, I suggest to make the selectors as generic as possible — By rewriting the LESS above as:

.main {

.sidebar {

.advert {

...

}

}

}

The coupling between HTML and LESS still exists, but now it is a beneficiary one — The LESS file describes the conceptual design of the markup it styles, not the implementation details.

Impossible to reuse

The fact that a selector is deeply nested, means it can’t be reused, unless the element that reuse it are located under the same ancestors.

To me this doesn't seem like a downside — In fact, it is the benefit of nesting. If you want the selector shared, for example a selector for a site-wide button design, it should be not nested in the first place.

Hard to override

The concern is as following:

.main {

.sidebar {

.advert {

...

}

}

}

If you would’ve liked to override .advert selector, like so:

.advert.special { ... }

It wouldn’t work — The nested .advert specificity is higher than the override.

This to me, again, isn’t an issue — .advert is nested and can only be used inside a sidebar element. If (and only if) there is a need to use .advert everywhere it should be un-nested, and put into the global scope.

However, if you want to make a special case for advert inside sidebar, overriding is easy:

.main {

.sidebar {

.advert {

... &.special { ... }

}

}

}

Performance

Nested selectors will create a long selector string in the output, e.g, LESS file from above would be processed to the following CSS:

.main .sidebar .advert { ... }

Such selectors were considered slow and recommended not to be used. These recommendations however are no longer valid. A benchmark (made a year ago) found very minimal differences between various selectors. Thus, performance seems to be not an issue in this discussion.

CSS file size

Nesting may cause the CSS file to grow, for example, consider this CSS result of LESS code that uses nesting:

.main { ... }

.main .sidebar { ... }

.main .sidebar .advert { ... }

Its non-nested version could look like that:

.main { ... }

.sidebar { ... }

.advert { ... }

It is hard to give exact numbers, but given the fact that most of the CSS file data are properties and not the selectors, I imagine that nesting could account up to at most 30% file size increase.

To answer this concern, I looked into the size of our own, quite large and deeply nested LESS file. It is transpiled to CSS file of 100kb. When minified this file becomes 80kb and when gzipped it becomes mere 12kb file, 30% of which is less than 4kb.

Due to that, it seems to be that size concern is also not an issue.

Summary

CSS allows us to define the style for the whole site. Since the best practice of styling dictate that the site UI, colors and fonts should be consistent, we should have global (not nested) selectors that define a consistent UX layer that is used across site. It should consists of paragraph fonts, header styles, and globally used components, like buttons and other reusable controls.

Another part of CSS, however, is more specific. Some elements, like the sidebar and its specific content can only be used in that specific scope. For that, nesting gives us the advantage of improved readability, simpler class names and reduced chance of unintentional changes.