CSS @layer is a powerful feature that helps you control the order and priority of your styles in a predictable way. Think of it as organizing your CSS into different levels or layers, where you decide which layer wins when styles conflict. Instead of relying on complex specificity calculations or the order of your stylesheets, you can explicitly define which styles should take precedence, making your CSS more maintainable and easier to understand.
In this tutorial, you will learn what CSS @layer actually is as a feature, why it solves common CSS problems, how to define and use layers with practical examples, and when to implement it in your projects.
What Exactly is CSS @layer?
CSS @layer is a CSS at-rule introduced to give developers explicit control over the cascade, which is how browsers decide which styles to apply when multiple rules target the same element. When you create a layer, you're essentially creating a container for your styles that has a specific priority level you control.
Each layer acts like a folder where you group related styles. Just like organizing files on your computer, you might have folders for "documents," "images," and "downloads"; with @layer, you might have layers for "reset," "components," and "utilities." The key difference from regular CSS is that you explicitly tell the browser which folder (layer) is more important.
Here's the basic syntax:
/* Declare your layers in order */
@layer first, second, third;
/* Add styles to a specific layer */
@layer first {
/* styles here */
}
The browser will always apply styles from third over second, and second over first, regardless of selector specificity.
The Problem @layer Solves in CSS
Before @layer came along, CSS developers faced constant battles with specificity. Let me show you a typical problem:
/* In your base styles */
.card {
background: white;
padding: 20px;
}
/* Later, a more specific selector */
div.card {
background: gray;
}
/* You want to override with a utility class */
.bg-blue {
background: blue;
}
<div class="card bg-blue">This card is gray, not blue!</div>
The card appears gray because div.card has higher specificity than .bg-blue. Without @layer, you'd need to increase specificity or use !important, both bad practices that make CSS harder to maintain.
How CSS @layer Changes the Game
With @layer, specificity within each layer still matters, but layers themselves have a clear hierarchy. Later layers always beat earlier ones:
@layer base, utilities;
@layer base {
/* This has higher specificity */
div.card.card {
background: gray;
padding: 20px;
}
}
@layer utilities {
/* But this still wins! */
.bg-blue {
background: blue;
}
}
<div class="card bg-blue">This card is blue!</div>
Now the card is blue because the utilities layer comes after the base layer. The specificity of div.card.card doesn't matter anymore; layer order is king.
Creating and Using Layers in CSS
You have two ways to work with layers. First, declare them all at once, then add styles:
/* Method 1: Declare first, define later */
@layer reset, base, components, utilities;
@layer reset {
* {
margin: 0;
padding: 0;
}
}
@layer components {
.btn {
background: blue;
color: white;
padding: 10px 20px;
}
}
Or create and define them simultaneously:
/* Method 2: Create and define together */
@layer reset {
* {
margin: 0;
}
}
@layer components {
.btn {
background: blue;
}
}
/* Order is determined by first appearance */
I prefer the first method because you see the hierarchy immediately at the top of your file.
Understanding Unlayered Styles
Here's something crucial: styles outside any layer have the highest priority. They beat everything:
@layer important {
.text {
color: red;
font-size: 20px;
}
}
/* This unlayered style wins */
.text {
color: green;
}
<p class="text">This text is green, not red</p>
Use unlayered styles sparingly, only for critical overrides that must always apply.
Complete Working Example of CSS @layer
Let's put everything together in a real-world example you can test:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS @layer Complete Demo</title>
<style>
/* 1. Declare layer order upfront */
@layer reset, base, components, utilities;
/* 2. Reset layer - Browser default overrides */
@layer reset {
button {
margin: 0;
padding: 0;
border: none;
background: none;
font: inherit;
}
}
/* 3. Base layer - Foundational styles */
@layer base {
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
padding: 20px;
}
button {
cursor: pointer;
transition: all 0.3s;
}
}
/* 4. Components layer - Specific component styles */
@layer components {
.btn {
background: #3b82f6;
color: white;
padding: 10px 24px;
border-radius: 6px;
font-weight: 500;
margin: 5px;
}
/* Even with high specificity */
button.btn.btn {
background: #2563eb;
}
.btn-success {
background: #10b981;
}
.btn-danger {
background: #ef4444;
}
}
/* 5. Utilities layer - Override helpers */
@layer utilities {
.bg-purple {
background: #a855f7;
}
.rounded-full {
border-radius: 9999px;
}
.text-lg {
font-size: 1.125rem;
}
}
/* 6. Unlayered styles - Emergency overrides */
.special-override {
background: #000 !important;
color: #ffd700 !important;
}
</style>
</head>
<body>
<h1>CSS @layer Demonstration</h1>
<section>
<h2>Different Layer Priorities:</h2>
<button class="btn">
Default Component Button
</button>
<button class="btn btn-success">
Success Button (Component Layer)
</button>
<button class="btn bg-purple">
Purple Button (Utility Wins)
</button>
<button class="btn btn-danger bg-purple rounded-full">
Multiple Utilities Override
</button>
<button class="btn bg-purple special-override">
Special Override (Unlayered)
</button>
</section>
<section style="margin-top: 30px; padding: 20px; background: #f3f4f6; border-radius: 8px;">
<h3>What's Happening:</h3>
<p><strong>Layer Order:</strong> reset → base → components → utilities → unlayered</p>
<ul>
<li>Button 1: Uses component layer styles (blue)</li>
<li>Button 2: Component layer with modifier (green)</li>
<li>Button 3: Utility layer overrides component (purple beats blue)</li>
<li>Button 4: Multiple utilities all apply, last layer wins</li>
<li>Button 5: Unlayered styles override everything (black/gold)</li>
</ul>
</section>
</body>
</html>
Live Preview:
See the Pen layer1 by Vinish Kapoor (@foxinfotech) on CodePen.
When Should You Use @layer?
CSS @layer shines in several scenarios. Use it when building design systems where utilities should always override components, working with third-party CSS libraries that you need to override cleanly, or managing large codebases where multiple teams contribute styles. It's also perfect for projects where you want to avoid !important and maintain clean specificity.
However, you might not need @layer for small, simple websites with minimal CSS, or if you're already using CSS-in-JS solutions that handle scoping differently.
See also: Scroll-Driven Animations in CSS
Conclusion
CSS @layer transforms how we manage style conflicts by replacing specificity wars with explicit layer ordering. You define your layers, organize your styles within them, and let the cascade work predictably. No more counting selectors or adding unnecessary !important declarations.
Try also: Duplicate CSS Remover Online Tool


