@layer CSS at-rule

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2022.

Style statements are read and interpreted in order they appear, meaning the last style always has precedence. The @layer CSS at-rule is used to declare new cascade layers. Multiple cascade layers can be defined to allow a greater control over precedency.

Styles that are not defined in a layer always come last and override styles declared in named and anonymous layers.

Try it

@layer module, state;

@layer state {
  .alert {
    background-color: brown;
  }
  p {
    border: medium solid limegreen;
  }
}

@layer module {
  .alert {
    border: medium solid violet;
    background-color: yellow;
    color: white;
  }
}
<p class="alert">Beware of the zombies</p>

Syntax

css
/* statement at-rules */
@layer layer-name;
@layer layer-name, layer-name, layer-name;

/* block at-rules */
@layer {rules}
@layer layer-name {rules}

where:

layer-name

Is the name of the cascade layer.

rules

Is the set of CSS rules in the cascade layer.

In block at-rules the layer-name can be ommited to define an anonymous layer. Comma seperated layer names dictate the order the layers are interpreted.

Description

Rules within a cascade layer cascade together.

The following diagram shows layer priorities where layers are declared in 1, 2, ..., N order.

Diagram showing cascade layer priorities

As noted in the above diagram, important declarations, declarations with the !important flag, have priority over normal declarations, or regular declarations without the !important flag. The order of precedence among important rules is the inverse of normal rules. Transitions have the greatest precedence. Next in order of highest to lowest priority are the important user agent declarations, important user declarations, and important author declarations; in that order. Users can specify styles using browser preferences, operating system preferences, or browser extensions. Their important declarations take precedence over author, or web developer written, important declarations.

Within author styles, all important declarations within CSS layers take precedence over any important declarations declared outside of a layer, while all normal declarations within CSS layers have a lower priority than declarations declared outside of a layer. The declaration order matters. The first declared layer gets the lowest priority and the last declared layer gets the highest priority. However, the priority is reversed when the !important flag is used.

The @layer at-rule is used to create a cascade layer in three ways.

Group rules in one layer

The first way is to use a @layer block at-rule to create a named cascade layer with the CSS rules for that layer inside, like so:

css
@layer utilities {
  .padding-sm {
    padding: 0.5rem;
  }

  .padding-lg {
    padding: 0.8rem;
  }
}

The rules in a layer can be specifed in multiple @layer block with the same name.

Ordering layers

Multiple layers are normally interpreted top to bottom. A @layer statement at-rule with one or more comma-separated names specify a new order. This can be a single layer, as shown below:

css
@layer utilities;

Multiple layers can be defined at once, as shown below:

css
@layer theme, layout, utilities;

This is useful because the initial order in which layers are declared indicates which layer has precedence. As with declarations, the last layer to be listed will win if declarations are found in multiple layers. Therefore, with the preceding example, if a competing rule was found in theme and utilities, the one in utilities would win and be applied.

A rule in utilities would be applied even if it has lower specificity than the rule in theme. This is because once the layer order has been established, specificity and order of appearance are ignored. This enables using simpler CSS selectors because you do not have to ensure that a selector will have high enough specificity to override competing rules; all you need to ensure is that it appears in a later layer.

Note: Having declared your layer names, thus setting their order, you can add CSS rules to the layer by re-using the name. The styles are then appended to the layer and the layer order will not be changed.

Anonymous layers

The third way is to create an unnamed layer using a @layer block at-rule without a layer name. For example:

css
@layer {
  p {
    margin-block: 1rem;
  }
}

This creates an anonymous cascade layer. This layer functions in the same way as named layers; however, rules cannot be assigned to it later. The order of precedence for anonymous layers is the order in which layers are declared, named or not, and lower than the styles declared outside of a layer.

Another way to create a cascade layer is by using @import. In this case, the rules would be in the imported stylesheet. Remember that the @import at-rule must precede all other types of rules, except @charset and @layer statements (not @layer blocks).

css
@import "theme.css" layer(utilities);

Nesting layers

Layers may be nested. For example:

css
@layer framework {
  @layer layout {
  }
}

To append rules to the layout layer inside framework, join the two names with a ..

css
@layer framework.layout {
  p {
    margin-block: 1rem;
  }
}

Formal syntax

@layer = 
@layer <layer-name>? { <rule-list> } |
@layer <layer-name># ;

<layer-name> =
<ident> [ '.' <ident> ]*

Examples

Basic example

In the following example, two CSS rules are created. One for the <p> element outside of any layer and one inside a layer named type for .box p.

Without layers, the selector .box p would have the highest specificity, and therefore, the text Hello, world! will display in green. As the type layer comes before the anonymous layer created to hold non-layer content, the text will be purple.

Also notice the order. Even though we declare the non-layered style first, it's still applied after the layer styles.

HTML

html
<div class="box">
  <p>Hello, world!</p>
</div>

CSS

css
p {
  color: rebeccapurple;
}

@layer type {
  .box p {
    font-weight: bold;
    font-size: 1.3em;
    color: green;
  }
}

Result

Assigning rules to existing layers

In the following example, two layers are created with no rules applied, then CSS rules are applied to the two layers. The base layer defines a color, border, font-size, and padding. The special layer defines a different color. As special comes last when the layers were defined, the color it provides is used and the text is displayed using rebeccapurple. All of the other rules from base still apply.

HTML

html
<div class="item">
  I am displayed in <code>color: rebeccapurple</code> because the
  <code>special</code> layer comes after the <code>base</code> layer. My green
  border, font-size, and padding come from the <code>base</code> layer.
</div>

CSS

css
@layer base, special;

@layer special {
  .item {
    color: rebeccapurple;
  }
}

@layer base {
  .item {
    color: green;
    border: 5px solid green;
    font-size: 1.3em;
    padding: 0.5em;
  }
}

Result

Specifications

Specification
CSS Cascading and Inheritance Level 5
# layering

Browser compatibility

See also