On this page
Cascade Layers (@layer)
CSS Cascade Layers (@layer): Control Specificity Wars
Focus keyword: CSS cascade layers. Cascade layers let you group your styles into named layers and decide which layer wins, no matter how specific the selectors are. They end the endless battle of !important, long selectors and file order. In this lesson you will learn how the cascade works, how to declare layers, how unlayered styles behave, how !important reverses the order, how to tame third party CSS and how to structure a real project.
Trending keywords covered in this lesson
CSS @layer, cascade layers tutorial, CSS specificity problems, layer order, unlayered styles, !important in layers, nested layers, revert-layer, @import layer(), CSS architecture, reset base components utilities, Tailwind layers, Bootstrap override, design system layers, CSS cascade order, DevTools layers, avoid !important, specificity wars.
1. A Quick Look at the Cascade
When two rules target the same property on the same element, the browser picks a winner using these steps, in order:
- Origin and importance: transitions, !important user agent, !important user, !important author, animations, normal author, normal user, normal user agent.
- Context (for example shadow DOM).
- Element-attached styles (inline style attribute).
- Cascade layers.
- Specificity.
- Scoping proximity.
- Order of appearance.
Layers sit before specificity. That is the key idea: a low specificity rule in a stronger layer beats a high specificity rule in a weaker layer.
2. Declaring Layers
- Statement form:
@layer reset, base, components, utilities;declares the layers and their order. The last layer listed wins for normal declarations. - Block form:
@layer components { .btn { ... } }adds rules to a layer. You can reopen the same layer many times and the rules are appended. - Anonymous layer:
@layer { ... }creates a layer with no name that cannot be referenced later.
Best practice: declare the order once at the very top of your main CSS file with a statement, then fill the layers anywhere.
3. Layer Order Beats Specificity
Imagine @layer base, components; with #page .btn { color: red } in base and .btn { color: blue } in components. The button is blue, because components is a later layer. The id selector does not help. The order in the file does not matter either, only the layer order.
4. Unlayered Styles Win
Any CSS outside a layer is treated as a final, implicit layer that comes after all named layers. For normal declarations, unlayered styles beat layered styles, whatever the specificity. This is useful for quick overrides, but it also means that if you forget to layer some of your own CSS, it can unexpectedly beat your organized layers. Put all of your code in layers for a predictable result.
5. !important Reverses the Order
For !important declarations the order is reversed: the earliest layer wins, and important unlayered styles are the weakest of all the important ones. This design lets a base layer or a reset protect critical rules. Use !important inside layers only for that purpose, not as a habit.
6. Nested Layers
Layers can contain layers: @layer framework { @layer base, theme; }. Refer to a child with a dot: @layer framework.theme { ... }. Nested layers are ordered inside their parent. This is handy for libraries and design systems.
7. Importing Third Party CSS into a Layer
Use @import url('bootstrap.css') layer(vendor); to put a whole file in a layer. Because your own layers declared later beat the vendor layer, you can override a library with simple selectors and no !important. @import rules must come before other rules, except @charset and @layer statements, so declare the order first, then import. You can also add a supports condition: @import url('x.css') layer(vendor) supports(display: grid);.
8. revert-layer
The keyword revert-layer rolls a property back to the value it would have in a previous layer. For example, .card { padding: revert-layer; } in a theme layer removes the theme change and restores the value from the layer before it. It is different from revert, which rolls back to the user agent or user origin.
9. A Practical Project Architecture
reset: modern reset, box-sizing, margin removal.base: typography, element defaults, variables.layoutorobjects: container, grid, stack.components: buttons, cards, navigation.utilities: helper classes such as.hiddenand.text-center, which should always win over components.
With @layer reset, base, layout, components, utilities; a utility class always beats a component without increasing specificity.
10. Frameworks and Tools
Modern tools already use layers. Tailwind CSS version 4 builds on native cascade layers, and many design systems publish their CSS inside a layer so that consumers can override it easily. If you use a framework that is not layered, wrap it with @import ... layer(vendor).
11. Debugging Layers
- Open DevTools, select the element and check the Styles panel. Browsers show the layer name next to each rule.
- Look at the computed panel to see which declaration won and which were overridden.
- If a rule does not apply, first check whether it is in an earlier layer than a competing rule, then check if an unlayered rule overrides it.
12. Browser Support
Cascade layers are supported in all current major browsers since 2022. If you must support very old browsers, rules inside an unknown @layer block are ignored completely, so use a build tool that flattens layers or keep a separate fallback stylesheet.
13. Common Mistakes
- Forgetting that unlayered CSS beats all layers.
- Listing the layers in the wrong order, for example putting utilities before components.
- Expecting file order to matter across layers.
- Using !important in a later layer and expecting it to win. Important declarations follow the reverse order.
- Placing @import after other rules so it is ignored.
- Creating too many layers. Four to six is enough for most projects.
- Expecting layers to change inline styles. Inline normal declarations still beat layers.
Key Takeaways
Cascade layers add a new step in the cascade before specificity. Declare the layer order once, put every rule in a layer, remember that the last layer wins for normal rules and the first wins for !important, keep unlayered CSS for deliberate overrides, and import third party CSS into a low priority layer to override it with simple selectors.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
The utility class .text-red never works because the component rule has a longer selector. Organize the CSS into layers (components first, utilities last) so that .text-red wins without !important and without changing the selectors.
Press Run to execute.
Show expected output
A layer order statement such as @layer components, utilities; with the component rule in components and .text-red in utilities, and the title becomes redThis is a self-check — compare your result with the expected output above.
Declare the layers reset, base, components and utilities in this order. Move the reset rule, the typography rule, the .btn rule and the .hidden helper into the correct layers.
Press Run to execute.
Show expected output
A statement @layer reset, base, components, utilities; and each rule placed in the matching @layer blockThis is a self-check — compare your result with the expected output above.
Was this page helpful?