The !important declaration in CSS overrides normal specificity rules:
.button {
background: blue;
}
.button {
background: red !important;
}
The button will be red, regardless of specificity. !important wins.
This power makes it dangerous when misused, but useful when applied correctly.
How !important Works
CSS resolves conflicting styles through specificity. IDs beat classes, classes beat elements:
#header .nav a { color: blue; } /* Specificity: 1-1-1 */
.nav a { color: red; } /* Specificity: 0-1-1 */
The first rule wins because IDs have higher specificity. But !important trumps everything:
.nav a { color: red !important; } /* Wins despite lower specificity */
Important declarations create a separate cascade layer. Within that layer, specificity applies normally. If two !important rules conflict, the more specific one wins:
#header .nav a { color: blue !important; } /* Wins */
.nav a { color: red !important; } /* Loses */
When !important Is Justified
Utility classes: Utilities should override component styles reliably:
.hidden { display: none !important; }
.text-center { text-align: center !important; }
.mt-0 { margin-top: 0 !important; }
When you add class="hidden", you expect the element to hide—regardless of what other styles apply. !important guarantees this.
Tailwind CSS uses !important on all utilities by default (when configured). This is intentional design.
Overriding third-party styles: Libraries you can't modify might set inline styles or high-specificity rules:
/* Third-party widget sets inline styles */
<div class="widget" style="color: blue;">...</div>
/* Your override */
.widget { color: red !important; }
Without !important, inline styles win. With it, you can override them.
State classes that must override: Error states, disabled states, and other critical UI states:
.is-error { border-color: red !important; }
.is-disabled { opacity: 0.5 !important; cursor: not-allowed !important; }
These states are exceptional. They should override normal styling consistently.
Print stylesheets: Print styles often need to override screen styles completely:
@media print {
.no-print { display: none !important; }
body { font-size: 12pt !important; }
}
When !important Is Wrong
To fix specificity problems in your own code: If you're using !important to beat your own selectors, the real problem is your selectors:
/* Bad */
.button { background: blue; }
#sidebar .button { background: red; }
.button { background: green !important; } /* Fighting your own specificity
/* Better */
/* Refactor to use consistent specificity */
.button { background: green; }
.button--primary { background: blue; }
.button--danger { background: red; }
As a first resort: Reaching for !important immediately means you're not understanding the cascade:
/* Bad - using !important instead of fixing selector */
.text { color: black !important; }
In base styles: Never use !important in your reset or base styles. It makes everything harder to override later:
/* Bad */
* { margin: 0 !important; padding: 0 !important; }
The Specificity War Problem
The worst outcome is a specificity war where multiple !important rules fight each other:
.button { background: blue !important; }
.primary-button { background: red !important; }
#header .button { background: green !important; }
Now you need to remember specificity within the !important layer. This defeats the purpose.
Alternatives to Consider First
Reduce specificity: Use classes instead of IDs, shallow selectors instead of deep ones:
/* Too specific */
#header nav ul li a { }
/* Better */
.nav-link { }
Increase specificity strategically: Repeat a class to increase specificity without !important:
.button.button { background: blue; } /* Beats single .button */
Use CSS custom properties: Variables can be overridden without !important:
:root { --button-color: blue; }
.button { background: var(--button-color); }
.primary { --button-color: red; } /* Overrides through variable */
Debugging !important
Browser DevTools show !important rules clearly. In Chrome, they're marked in the Styles panel. Crossed-out rules show what was overridden and why.
If a style isn't applying, check:
- Is there an
!importantrule overriding it? - What's the specificity of competing rules?
- Are there inline styles taking precedence?
Frameworks and !important
CSS frameworks use !important strategically:
Bootstrap: Uses it sparingly for utilities like .d-none (display: none)
Tailwind: Can be configured to add !important to all utilities with the important option
Material-UI: Provides an important prop for style overrides when needed
These frameworks understand that utilities need reliable override behavior.
Code Review Guidelines
When reviewing CSS, flag !important usage and ask:
- Is this a utility class? (Probably fine)
- Is this overriding third-party code? (Acceptable)
- Is this fighting our own specificity? (Refactor needed)
- Could we solve this by reducing specificity elsewhere? (Better approach)
CSS Cascade Layers
CSS Cascade Layers (CSS Cascading Level 5) provide a better solution for some !important use cases:
@layer reset, base, components, utilities;
@layer utilities {
.hidden { display: none; } /* No !important needed */
}
Layers let you define precedence explicitly. Utilities in the utilities layer automatically override components without !important.
Browser support is improving. This is the future of managing cascade order.
Performance Impact
!important has negligible performance impact. The browser's CSS engine handles it efficiently. The cost is maintainability, not speed.
Migration Strategy
Cleaning up overused !important:
- Audit: Find all
!importantdeclarations - Categorize: Which are justified? Which aren't?
- Refactor unjustified cases: Fix underlying specificity issues
- Document justified cases: Add comments explaining why
/* Override third-party widget inline styles */
.widget { color: red !important; }
Further Reading
MDN's guide to CSS specificity explains how the cascade works and when !important applies.
Harry Roberts' article "The Importance of !important" makes the case for strategic use.
The CSS Cascade Level 5 specification covers cascade layers as an alternative.
!important isn't inherently bad. It's a tool. Used correctly for utilities, third-party overrides, and exceptional states, it solves real problems.
0 comments