skip to Main Content

With this style

div {
  @media (min-width: 0px) {
     color: blue;
  }
  color: red;
}
<div>
hello
</div>

I expect the color to be red. However, it’s actually blue and I have no explanation for this. Tested on Chrome. The color is red in other browsers.

2

Answers


  1. This is because the nested @rule actually unwraps to

    @rule {
      & {
        /* ... */
      }
    }
    

    This is explained in this paragraph of the specs, which even contains an example pointing out this case:

    .foo {
      display: grid;
    
      @media (orientation: landscape) {
        grid-auto-flow: column;
      }
    }
    /* equivalent to
      .foo {
        display: grid;
    
        @media (orientation: landscape) {
          & {
            grid-auto-flow: column;
          }
        }
      }
    */
    

    And if we do add the & selector to the color: red rule, we get the same specificity:

    div {
      @media (min-width: 0px) {
         color: blue;
      }
      & { color: red; }
    }
    <div>
    hello
    </div>

    And note that your code currently produces a red output in non Chromium browsers because they still don’t support CSS nesting, so they just treat the @media rule here as an invalid rule and go on to parse the div one.
    If you want to support all browsers, you have to manually unwrap these rules:

    @media (min-width: 0px) {
      div { color: blue; }
    }
    div {
      color: red;
    }
    <div>
    hello<!-- will be red everywhere -->
    </div>
    Login or Signup to reply.
  2. I will use another example to illustrate your issue:

    div {
      & {
        color: blue;
      }
      color: red;
    }
    <div>
      hello
    </div>

    We are mixing "nested rules" and "declarations" and the Specification defines such behavior by moving the "nested rules" at the end.

    So the browser will change your code to this:

    div {
      color: red;
      & {
        color: blue;
      }
    }
    <div>
      hello
    </div>

    And then to this:

    div {
      color: red;
    }
    
    div {
      color: blue;
    }
    <div>
      hello
    </div>

    So always start with the "declarations" then the "nested rules"

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search