14
头图

Entering 2022, new features of CSS are emerging in an endless stream, and the new feature that has attracted the most attention in the CSS circle recently is CSS @layer.

This article will use the most concise language to quickly let readers understand what is the new CSS @layer specification.

Issues with past CSS prioritization

If there are a lot of styles on our page, for example, there are custom styles when we develop pages, and there are also imported component library styles. this time, the style will be very confusing and difficult to manage .

When we want to override some styles that are not written by us, we often have to override those styles by using a style name with a higher priority.

At the same time, when style priorities feel uncontrollable, developers are accustomed to abusing !important to solve them, which in turn leads to more confusing style structures in the future.

CSS @layer came into being based on the background of allowing CSS to be better controlled and managed.

What is CSS @layer?

CSS @layer is defined by the specification from CSS Cascading and Inheritance Level 5 .

What is CSS @layer? In simple terms, @layer in CSS declares a cascading layer, rules within the same layer will be cascaded together, which gives developers more control over the cascading mechanism.

The syntax is also very simple, look at this example:

@layer utilities {
  /* 创建一个名为 utilities 的级联层 */
}

This way, we create a @layer cascade called utilities.

How to use @layer cascade layer?

Manage style priority via @layer cascading layers

The biggest function of the cascade layer is to control the priority between different styles.

Consider the following example where we define two @layer cascading layers A and B:

<div></div>
div {
    width: 200px;
    height: 200px;
}
@layer A {
    div {
        background: blue;
    }
}
@layer B {
    div {
        background: green;
    }
}

Since the order of @layer B @layer A after @layer B , all styles in 0623afdbdb934b will have higher priority than @layer A , and the final div color will be green :

Of course, if there are too many @layers in the page, it may be difficult to remember the order of all @layers, so there is such a way of writing.

We can name multiple @layer layers at the same time, and then supplement the style rules in them.

<div></div>
@layer B, C, A;
div {
    width: 200px;
    height: 200px;
}
@layer A {
    div {
        background: blue;
    }
}
@layer B {
    div {
        background: green;
    }
}
@layer C {
    div {
        background: orange;
    }
}

In the above code, we first define three @layer B, C, A cascade layers of 0623afdbdb93ae. Then, the CSS code of each cascade layer is supplemented in the following CSS code, but the priority of the style is:

A > C > B

So the color value of the final div is the color defined in @layer A, which is blue :

At this point, the role of CSS @layer can be clearly seen.

Using CSS @layer, we can divide different modules of CSS into different @layers, and use the sequence to control the global style priority very well .

Three ways to define the introduction of @layer cascading layers

The above actually mentioned two ways of introducing the definition of the @layer cascading layer. Here, there are three ways to introduce the CSS @layer cascading layer.

  1. Create a block-level @layer rule directly containing CSS rules that act inside the layer:
@layer utilities {
  p {
    padding: .5rem;
  }
}
  1. A cascading layer can be created by @import , the rules exist in the imported stylesheet:
@import(utilities.css) layer(utilities);
  1. Creates named cascading layers without specifying any styles. Styles can then be added anywhere within the CSS:
@layer utilities;
// ...
// ...
@layer utilities {
    p {
        color: red;
    }
}

Non-@layer-wrapped and @layer-in-layer styles take precedence

Of course, there will be a situation here. What is the priority of the style not wrapped by @layer compared to the style wrapped by @layer?

See an example like this:

@layer A { a { color: red; } }
@layer B { a { color: orange; } }
@layer C { a { color: yellow; } }
a { color: green; } /* 未被 @layer 包裹的样式 */ 

There will be a very important conclusion here, non-@layer wrapped styles have higher priority than @layer wrapped styles , so the ordering of the above rules is:

Styles not wrapped by @layer > @layer C > @layer B > @layer A

Anonymous and nested layers

There are also two hierarchical relationships, namely anonymous layer and nested layer .

anonymity layer

Allows to create a @layer without a name:

@layer {
  p {
    margin: 1rem;
  }
}

Here, an anonymity layer is created. Two important properties of the anonymity layer:

  1. Can't add rules to it after creation
  2. This layer has the same function as other named layers, and the priority also follows the anonymous layer defined later, which is higher than other defined @layer layers.

See an example:

<div></div>
div {
    width: 200px;
    height: 200px;
}
@layer {
    div {
        background: pink;
    }
}
@layer B, C, A;
@layer A {
    div {
        background: blue;
    }
}
@layer B {
    div {
        background: green;
    }
}
@layer C {
    div {
        background: orange;
    }
}

In the above code, we first define an anonymous layer, specify the color of the div as pink , and then define @layer B, C, A . Here the priority order is:

A > C > B > Anonymity Layer

The final color is the color value inside @layer A -- blue :

If, we put the anonymity layer last:

div {
    width: 200px;
    height: 200px;
}
@layer B, C, A;
@layer A {
    div {
        background: blue;
    }
}
@layer B {
    div {
        background: green;
    }
}
@layer C {
    div {
        background: orange;
    }
}
@layer {
    div {
        background: pink;
    }
}

At this point, the precedence order of styles is:

Anonymous layer > A > C > B

The final color is the color value inside the anonymous layer -- pink :

nested layer

After talking about the anonymous layer, let's look at the nested layer.

As the name suggests, the nested layer means that inside the @layer, we can nest and use the @layer cascade layer. Like this:

@layer A {
  @layer B{
    ...
  }
}

Of course, it has another syntax, the above code is equivalent to:

@layer A.B {
  ...
}

After understanding this, then, look at this example:

<div></div>
div {
    width: 200px;
    height: 200px;
}
@layer A {
    div {
        background: blue;
    }
    
    @layer B {
        div {
            background: red;
        }
    }
}

We nest a @layer B in @layer A, and define a div style at the same time. What color is background of the final div?

It ends up being blue background: blue , why? This is a good memory. We assume that if there is no @layer A layer of wrapping, it is actually the priority comparison between the @layer layer and the non-@layer layer mentioned above. Here, the non-@layer layer (we can understand it as a higher level A layer @layer) has higher priority.

So, for nested relationships within a single @layer, style precedence is:

@layer A > @layer A.B

The priority relationship of multiple nested layers

OK, let's look at this situation:

div {
    width: 200px;
    height: 200px;
}
@layer A {
    div {
        background: blue;
    }
    @layer B {
        div {
            background: red;
        }
    }
}
@layer C {
    div {
        background: yellow;
    }
    @layer D {
        div {
            background: green;
        }
    }
}

There are cases where there are multiple nested @layers at the same time. So how is the priority divided in this case?

The rule here is that a @layer with a higher priority, regardless of whether there is nesting, has overall higher priority than a @layer with a lower priority (whether there is nesting or not). Therefore, the priority ordering here is:

@layer C > @layer C.D > @layer A > @layer A.B

The effect of !important on CSS @layer

Let's take a look at the effect of !important on CSS @layer.

There are several cases here, let's look at one of them first:

<div></div>
div {
    width: 200px;
    height: 200px;
    background: black;
}
@layer A {
    div {
        background: blue;
    }
    @layer B {
        div {
            background: red;
        }
    }
}
@layer C {
    div {
        background: yellow;
    }
    @layer D {
        div {
            background: green!important;
        }
    }
}

In the above code, we add a !important rule to 0623afdbdb98da of <div> CD.

If, without considering !important rule, the actual CSS priority is (the higher the serial number, the higher the priority):

  1. @layer A.B
  2. @layer A
  3. @layer C.D
  4. @layer C
  5. non-layer wrapping blocks

Then, the color of <div> should be black black . However, here's a !important rule added to @layer CD's <div> .

In fact, the final color of <div> is green , that is, the final priority order is (the higher the serial number, the higher the priority):

  1. @layer A.B
  2. @layer A
  3. @layer C
  4. non-layer wrapping blocks
  5. @layer CD under !important

That is to say, the priority of the !important rule is still higher than the non- !important rule.

The above demo is quite interesting. If you are interested, you can check it out: CodePen Demo -- CSS Cascade @layer Demo

Non-@layer containing block !important vs @layer containing block !important

At this point, you may think you understand. Ok, let's look at another demo, if we add a !important rule to the non-@layer containing block, things get interesting.

<div></div>
div {
    width: 200px;
    height: 200px;
    background: black!important;
}
@layer A {
    div {
        background: blue;
    }
    @layer B {
        div {
            background: red;
        }
    }
}
@layer C {
    div {
        background: yellow;
    }
    @layer D {
        div {
            background: green!important;
        }
    }
}

Looking at the above code carefully, we have also added a !important rule for non-@layer containing blocks. According to the rules I can describe above, non-@layer containing blocks have higher priority than @layer containing blocks, so normally, It is not difficult to guess that the priority of background: black!important should be higher than that of background: green!important , and finally <div> should display black.

In fact, the final color of <div> is green . Here is another very interesting point of knowledge. The rules of style priority under !important are exactly opposite to those under normal non-!important state.

This is a very important feature. When comparing normal (non- !important ) rules, the more cascading (the later @layer rules), the lower the priority; on the contrary, when comparing !important rules, the more cascading and relying The latter (the later @layer rules in the order), the higher the priority.

This, further, we need to understand CSS Cascading related knowledge.

CSS Cascade Specification

Before CSS @layer, we simply look at a picture:

The above picture shows the priority order of CSS style declarations before CSS @layer is . According to the CSS Cascading 4 (Current Work) standard, the priority of the cascading order declared under the current specification is as follows (the further down The higher the priority, the following rules are in ascending order):

  • Normal user agent declarations
  • Normal user declarations
  • Normal author declarations
  • Animation declarations
  • Important author declarations
  • Important user declarations
  • Important user agent declarations
  • Transition declarations

According to the above algorithm, you can get a sort of style priority, which is probably like this (the lower the priority, the higher the priority, and the following rules are arranged in ascending order):

  1. User Agent - User agent plain style
  2. User - the normal style set by the user
  3. Author - page author normal style
  4. Animations - Animation styles
  5. ❗️Author - author of the page! important style
  6. ❗️User - !important styles set by the user
  7. ❗️User Agent - !important styles for user agents
  8. Transitions - Transition styles
briefly explains :
User-Agent Style : Browsers will have a basic style sheet to set the default style for any web page. These styles are collectively referred to as user agent styles
Page Author Styles : The author of a web page can define the style of the document, which is the most common style sheet. In most cases, multiple style sheets of this type are defined, which constitute the visual and experience of the website, that is, the page theme, which can be understood as the page author style
user style : readers, as browser users, can use custom style sheets to customize the user experience and customize user preferences, which can be understood as user styles

Regarding CSS Cascading, which is the cascading specification, you can read my article to deepen your understanding -- -depth understanding of Cascading in CSS (Cascading Style Sheets) .

And when there is CSS @layer, this cascading priority order has been updated, the specific priority is as follows:

The whole will be changed to be more complex, but the whole still follows two rules:

  1. !important style is higher than non- !important style
  2. When comparing the !important rules, the priority order is opposite to the normal rules, the lower the priority in the normal state, the higher the priority under !important

in conclusion

To sum up, it is the basic knowledge about CSS @layer.

The birth of CSS @layer enables us to better divide the style hierarchy of the page and better handle the priority order of internal styles and external reference styles, which is a relatively major innovation.

At the same time, it also made us realize that we should gradually abandon the wrong practice of using !important to override style priority on a large scale, and avoid many unnecessary side effects caused by priority problems.

Of course, as of today (2022-03-14), let's take a look at compatibility:

Although it has become popular, CSS @layer has been supported in the latest versions of Chrome, Safari, Firefox, and Edge, and it can be used initially through some polyfills. I believe it will become a business in the near future. An essential part of CSS code.

Further reading

There have been a lot of discussions on CSS @layer on the Internet. Here are some high-quality articles. If you are interested, you can continue to read:

finally

Well, this is the end of this article, I hope it helps you :)

If you want to get the most interesting CSS information, don't miss my official account -- iCSS front-end anecdote 😄

More wonderful CSS technical articles are summarized in my Github -- iCSS , which is continuously updated. Welcome to click a star to subscribe to the collection.

If you have any questions or suggestions, you can communicate more. Original articles are limited in writing and knowledge. If there are any inaccuracies in the article, please let me know.


chokcoco
12.3k 声望18.5k 粉丝