Selector Nesting Has Come to CSS 🤯🤯🤯 !!!

11786 words scsshtmlcsssaascss

First we had variables and now nesting in css! It seems that the functionality we get with pre-processors like Sass and Less are slowly being introduced in CSS. It's similar to what's happening between javascript and typescript. If you have noticed, a few years ago, some of the current javascript features did not exist in javascript but were implemented in typescript.

I'm not saying this is a bad thing, it's actually great! This decreases the need for pre-proccessors which need to be compiled into CSS/Javascript

That being said, selector nesting is still in the future. No browsers support it yet, but I expect this to improve. For more information, checkout the draft.

What Really Is nesting???

To explain this effectlively, I'm going to compare two code samples.

Without Nesting
button.btn {
  color: blue;
  background: white;
  transition: .2s all ease-in;
  /* More styles for the button */
}

button.btn:hover {
  color: white;
  background: blue;
}

button.btn:focus {
   /* Add more styles */
}

button.btn-group {
  /* Some styles */ 
}

button.btn-primary {
  /* I promise, this is the last. */ 
}

Now let me show the same code with nesting.

.btn {
  color: blue;
  background: white;
  transition: .2s all ease-in;

  &:hover {
    color: white;
    background: blue;
  }

  &:focus {
   /* Add more styles */
  }

  &-group {
    /* Some styles */ 
  }

  &-primary {
    /* You get the point right??? */ 
  }
}

Just like in Sass, The & is used to refer to the parent selector(in this case, .btn). That's not all, we can also nest multiple levels deep.

.btn {
  color: white;
  background: cyan;

  &-container {
    margin: 10px 20px;

    &:hover {
      /* Some fancy animation */ 
    }

    & .overlay {
       /* There should always be an "&" in a nested selectors */
    }
  }
}

@nest

This is a new at-rule that helps us overcome some of the limitations of nesting using the &. Look at the following code:

.section {
    /* etc ... */
}

.section {
    /* etc ... */

    .blog {
        /* We want to reference the blog container which is inside the .section. */
    }
}

For this, we can use the @nest rule. This rule shifts the reference of the & to another selector we specify.

.main {
    /* etc ... */

    .blog {
        @nest .section & {
                        /* The "&" refers to ".section" */
            background: red;
        }
    }
}

Nesting Media Queries

For people who are familiar with Sass, the "normal" code looks like this:

.section {
  @media(/* some media query */) {
    /* styles... */
  }

}

However, this is slightly different. In css, the styles must be enclosed in "&".

  @media(/* some media query */) {
    & {
      /* styles... */
    }
  }
  • Normal code
.table.xyz > th.y > p.abc {
  font-size: 1rem;
  color: white;
}

.table.xyz > th.y > p.abc-primary {
  font-size: 1.4rem;
}
  • The Power of nesting 💪 💪 💪
.table.xyz > th.y > p.abc {
  font-size: 1rem;
  color: white;

  &-primary {
    font-size: 1.4rem
  }
}

Makes code more readable

As soon as you look the code, you can go "Aha, anything between those outer curly braces is related to buttons or .btn! Not my business!"

A gotcha

One thing to keep in mind is that any css which is after nested selectors is flat out ignored. However, any nesting that is followed is completely valid.

.x {
  &-y {
    /* styles... */
  }

  a {
    /* invalid */
  }

  &-z {
    /* valid */
  }
}

That's it guys! Thank you for reading this post. Please give it a like and follow me on dev.to for more content based on HTML & CSS, Javascript, React and NodeJS. To my dear regular readers, I'm sorry about not writing any articles in the past few weeks, I was quite busy. Bye guys 🤟