Cascade Layers?

Avatar of Chris Coyier
Chris Coyier on (Updated on )

Take your JavaScript to the next level at Frontend Masters.

There is a new thing coming in CSS: @layer. As with all new things, it takes time to really wrap your head around it. And despite me tapping at my keyboard about it, full disclosure, I’m not sure my mind is fully there yet. Fortunately, smart people are on the case!

This comes from Miriam Suzanne, who is really on a tear with influencing important new CSS stuff. I’ve been hearing about all this, but then all the sudden it just dropped in experimental browsers:

I had this really simplistic view of what the plan was with layers. Say you link up two CSS files:

<link rel="stylesheet" href="1.css">
<link rel="stylesheet" href="2.css">

Anything selectors in 2.css will “win” over selectors the same specificity as something in 1.css. I thought CSS layers was a way to control that without needing to change the source order of those stylesheets in HTML. So, no matter where you load a reset stylesheet, you can kinda notch down the importance of it by kicking it to an earlier layer. Or, no matter where you load an overrides stylesheet, you can kick it up.

I think that kind of thing might be coming still, but the actual concept of layers is much more powerful than I first imagined.

Leave it to Bramus to really dig into all this with a fantastic post on it all:

With Cascade Layers coming, we developers will have more tools available to control the Cascade. The true power of Cascade Layers comes from its unique position in the Cascade: before Selector Specificity and Order Of Appearance. Because of that we don’t need to worry about the Selector Specificity of the CSS that is used in other Layers, nor about the order in which we load CSS into these Layers — something that will come in very handy for larger teams or when loading in third-party CSS.

Bramus Van Damme, “The Future of CSS: Cascade Layers (CSS @layer)

Emphasis mine.

That’s the rub here: this is a new thing that affects which selectors win. It’s going to require some re-wiring of our CSS brains, because layers is this entirely new (and powerful) part of determining what styles actually get applied.

I say powerful because a “higher” layer can literally beat a traditionally stronger selector even with a weaker selector in the layer.

Miriam’s support demo makes this clear in a few lines:

/* layers override unlayered styles */
@layer override {
  h1 {
    color: green;
  }

  h1::before {
    content: "✅ ";
  }
}

/* despite the higher specificity */
#h1 {
  color: red;
}

#h1::before {
  content: "❌ ";
}

Because that CSS at the bottom isn’t in a layer at all, the layered CSS wins, even with the weaker selectors. Wow.

And you aren’t limited to one layer. You get to define them and use them however you want.

@layer reset;     /* Create 1st layer named “reset” */
@layer base;      /* Create 2nd layer named “base” */
@layer theme;     /* Create 3rd layer named “theme” */
@layer utilities; /* Create 4th layer named “utilities” */
/* Or, @layer reset, base, theme, utilities; */


@layer reset { /* Append to layer named “reset” */
  /* ... */
}

@layer theme { /* Append to layer named “theme” */
  /* ... */
}

@layer base { /* Append to layer named “base” */
  /* ... */
}

@layer theme { /* Append to layer named “theme” */
  /* ... */
}

Mind-blowing, really.

How are we going to use this?

I wonder if a common pattern might turn into…

  1. Not layering our resets, so they are extra weak.
  2. Layering third-party imports at a low level.
  3. Layering any authored styles at a high level.

And then not really worrying if you leave space between the layers because you can adjust layers any time.

Time shall tell.

I bet we’ll see people dip their toes with:

/* This is our only layer. Anything in here wins. */
@layer overrides { 
  /* ... */
}

And then a couple years later:

@layer final { 
  /* ... */
}
@layer final-final { 
  /* ... */
}
@layer final-final-v2 { 
  /* ... */
}
@layer final-final-final-last-complete { 
  /* ... */
}

Debugging

I hope DevTools expresses layers really clearly because there is going to be some serious head-scratching for a while when we see weaker-looking selectors winning because of layer placement.

Browser Support

Looks like caniuse is on the ball here!

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
NoNoNoNoNo

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
NoNoNoNo

Updates

This stuff is super new (at the time of writing), so volatility is to be expected, I suppose. Looks like on October 6th, 2021 it was decided that unlayered styles are actually the strongest styles, not the weakest, which flips a lot of the above on it’s head.