The gotchas of CSS Nesting

I’ve written before about the problems you can run into with CSS nesting (keep in mind that article uses an older syntax but the point still stands) and the question that @ChallengeCSS tweeted out today made me realize there’s actually a few more gotcha’s. Here’s what they tweeted: Everyone is exited about CSS Nesting but […]

The post The gotchas of CSS Nesting first appeared on Kilian Valkhof.


This content originally appeared on Kilian Valkhof and was authored by Kilian Valkhof

I've written before about the problems you can run into with CSS nesting (keep in mind that article uses an older syntax but the point still stands) and the question that @ChallengeCSS tweeted out today made me realize there's actually a few more gotcha's. Here's what they tweeted:

Take a moment to come up with your own answer (or vote), then read on.

Now, I initially got it wrong. Here was my thinking pattern:

  1. @media doesn't add specificity, so both declarations have a specificity of 0,0,1
  2. background: blue comes later, so it wins

But no, the background is red! It turns out that has to do with the way browsers transform your nested CSS rules to individual rules it can apply. So lets dive into how browsers do that.

A related gotcha, :is()

Last week was CSS Day (which was amazing) and of course a bunch of the presentations mentioned CSS Nesting. Unfortunately, some had a simplified explanation of how rules get resolved.

The & in nested CSS isn't just replaced by the ancestor, which is what you might think, but it's ancestor is also wrapped in :is():

body {
    & div {
        ...
    }
}

/* Doesn't become this: */
body div { ... }

/* It becomes this: */
:is(body) div { ... }

Now that doesn't sound like there is much of a difference between body div and :is(body) div, indeed both have a specificity of 0,0,2, but remember that:is() takes on the highest specificity of the selectors in it. So when you have the following:

main, #intro {
    & div {
        ...
    }
}

The resulting selector, even when targeting a div in main, ends up as:

:is(main, #intro) div { ... }

Which makes it go from 0,0,1 for main div to 1,0,1 making it vastly more specific. That gotcha gets lost when examples fail to include the way ancestors are wrapped in :is() (and yes, they also nest :is()!)

Back to the original gotcha

So back to the challenge up top. You can intermingle properties and nesting. You shouldn’t to keep your code readable, but the following CSS works just fine and applies all the styling:

body {
  filter: blur(5px);
  
  @media all {
    background: red;
  }
    
  background: blue;
  
  @media all {
    color: deeppink;
  }
  
  rotate: 20deg;
}

It's when the browser parses this CSS into individual rules that the sneaky thing happens:

  1. The browser adds a new ruleset, body, and starts adding the properties to it/
  2. The browser then adds another new ruleset for the nested media query and starts adding its properties to it/
  3. When it exits the nested media query, it adds the rest of the properties to the original ruleset again until that is exited.

So if we look at this CSS again:

body {
    @media all {
        background: red;
    }
    background: blue;
}

That actually resolves to these two rules in this specific order:

body {
    background: blue;
}
@media all {
    :is(body) {
        background: red;
    }
}

Now from this CSS, it makes more sense that red wins. It has the same specificity but it comes after the first rule so it wins. And that's the gotcha.

This post originally claimed that only @-rules could be intermingled with properties but this was incorrect. Thanks @ChallengesCSS for correcting me.

The post The gotchas of CSS Nesting first appeared on Kilian Valkhof.


This content originally appeared on Kilian Valkhof and was authored by Kilian Valkhof


Print Share Comment Cite Upload Translate Updates
APA

Kilian Valkhof | Sciencx (2023-06-13T10:53:17+00:00) The gotchas of CSS Nesting. Retrieved from https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/

MLA
" » The gotchas of CSS Nesting." Kilian Valkhof | Sciencx - Tuesday June 13, 2023, https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/
HARVARD
Kilian Valkhof | Sciencx Tuesday June 13, 2023 » The gotchas of CSS Nesting., viewed ,<https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/>
VANCOUVER
Kilian Valkhof | Sciencx - » The gotchas of CSS Nesting. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/
CHICAGO
" » The gotchas of CSS Nesting." Kilian Valkhof | Sciencx - Accessed . https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/
IEEE
" » The gotchas of CSS Nesting." Kilian Valkhof | Sciencx [Online]. Available: https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/. [Accessed: ]
rf:citation
» The gotchas of CSS Nesting | Kilian Valkhof | Sciencx | https://www.scien.cx/2023/06/13/the-gotchas-of-css-nesting/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.