'Background color overridden even after reversing the order of CSS layers

I want to use the new CSS cascade layers feature supported by latest versions of Chrome, Firefox, Safari, and Edge (see the support table).

I'm importing a stylesheet from highlight.js. It has a class named hljs that applies a background color to <code> elements. I want to override that color with CSS @layer rules:

@import url("styles/base16/google-light.min.css") layer(highlightjs);

@layer highlightjs, main;

@layer main {
  .hljs {
    background: red;
  }
}

This works and overrides the background color but when I reverse the order of layers, still my background color applies. Why is that?

@layer main, highlightjs;


Solution 1:[1]

The issue is that your @import provides the first naming of the "highlightjs" layer. It comes before the list of layers, so it makes it the lowest precedence layer. The list of two layers then has no effect.

@import url("data:text/css, code { background:blue; color:yellow }") layer(highlightjs);

@layer main, highlightjs;

@layer main {
  .hljs {
    background: red;
  }
}
<code class="hljs">
  Hello World
</code>

For this reason, an @layer list is allowed to precede an @import. In the snippet below, the order of layers is main, then highlightjs, and the colouring is adjusted appropriately.

@layer main, highlightjs;

@import url("data:text/css, code { background:blue; color:yellow }") layer(highlightjs);

@layer main {
  .hljs {
    background: red;
  }
}
<code class="hljs">
  Hello World
</code>

Solution 2:[2]

CSS cascade layers, a CSS feature that allows us to define explicit contained layers of specificity, so that we have full control over which styles take priority in a project without relying on specificity.

@layer reset, defaults, framework, components, utilities;

That will establish the layer order:

  1. un-layered styles (most powerful)
  2. utilities
  3. components
  4. framework
  5. defaults
  6. reset (least powerful)

but remember: what matters is the order each name first appears. So this will have the same result:

@layer reset, defaults, framework;
@layer components, defaults, framework, reset, utilities;

layers are stacked based on the order in which the layers first appear in your code

check this css-tricks.com/css-cascade-layers for further clarifications.

Solution 3:[3]

I look at anything that overrides specificity as a really, really bad idea. And the fact they they are pushing badly thought out features like @layer simply to accommodate people that can't get their heads around specificity is mind boggling. Do yourself a favor and don't use @layer, if you do you will soon find yourself in CSS hell where you have no idea what happens when and why. Stick to 2 simple rules :

  1. use scoping for overriding
  2. use !important ONLY to override inline style that you have no control over.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 DevThiman
Solution 3 Panagiotis Sakellariou