CSS Cascade Layers (@layer)
Cascade layers let you put your CSS into ordered groups. A later layer always wins over an earlier one, no matter how specific the selectors are.
The Problem Layers Solve
In big projects, CSS comes from many places: a reset, a framework like Bootstrap, your own components, small helper classes. When they fight, you often end up writing longer selectors or adding !important just to win. That makes the CSS worse every month.
With layers, you decide the order of importance once, at the top of the file.
Creating Layers
Write @layer with the names, in order from weakest to strongest:
Example
@layer reset, base, components, utilities;Then put rules into a layer with a block:
Example
@layer reset {
* { margin: 0; box-sizing: border-box; }
}
@layer base {
a { color: #264de4; }
}
@layer components {
.btn { padding: 8px 16px; border-radius: 6px; }
}
@layer utilities {
.hidden { display: none; }
}The order comes from the first @layer line, not from where each block is written in the file.
Layers Beat Specificity
This is the key idea. Between two layers, the layer order decides, and specificity is only compared inside the same layer.
Example
<!DOCTYPE html>
<html>
<head>
<style>
@layer base, components;
@layer components {
.title {
color: seagreen;
}
}
@layer base {
#page h1.title {
color: crimson;
}
}
</style>
</head>
<body id="page">
<h1 class="title">Workownix Tutorials</h1>
</body>
</html>Try it Yourself »The heading is green. #page h1.title is much more specific, but it is in the base layer, which comes before components.
The Cascade Order with Layers
For normal (not !important) styles, the browser checks in this order, from weakest to strongest:
| Step | Source |
|---|---|
| 1 | Browser's default styles |
| 2 | Your first layer |
| 3 | Your later layers, in order |
| 4 | Styles that are not in any layer |
| 5 | Inline style="" attributes |
So unlayered CSS beats all layered CSS. This is useful: if you put a framework in a layer, your own plain CSS beats it easily.
!important works the other way round with layers: an !important rule in an early layer beats one in a later layer. This lets a reset layer protect its most important rules.
Putting a Framework in a Layer
You can import a whole stylesheet straight into a layer:
Example
@import url("bootstrap.min.css") layer(framework);
@layer framework, custom;
@layer custom {
.btn {
border-radius: 999px; /* beats Bootstrap's .btn rules */
}
}@import must be at the very top of the CSS file, before other rules.
Nested Layers and Anonymous Layers
Layers can contain layers. You refer to them with a dot:
Example
@layer components {
@layer cards {
.card { padding: 16px; }
}
}
/* Add more to the same nested layer later */
@layer components.cards {
.card h3 { margin-top: 0; }
}A layer without a name (@layer { ... }) is anonymous. You cannot add to it later, so named layers are usually better.
A Complete Structure
Example
<!DOCTYPE html>
<html>
<head>
<style>
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer base {
body { font-family: Arial, sans-serif; padding: 20px; }
p { margin-bottom: 12px; }
}
@layer components {
.alert {
padding: 12px;
border-radius: 6px;
background-color: #fef3c7;
color: #92400e;
}
}
@layer utilities {
.mb-0 { margin-bottom: 0; }
.center { text-align: center; }
}
</style>
</head>
<body>
<p class="alert">Fee deadline: 25 October.</p>
<p class="alert mb-0 center">Results will be announced on Friday.</p>
</body>
</html>Try it Yourself »The small helper classes in utilities always win over components, so .mb-0 works without !important.
Exercise
Exercise
You declare @layer base, theme; A rule in base uses an id selector, and a rule in theme uses only a class. Which wins?
