CSS !important: What It Does and When to Use It
Contents
- How !important fits into the cascade
- How to override an !important rule
- !important and cascade layers
- When !important is the right tool
- Utility classes that must always apply
- Overriding inline styles you don't control
- Respecting user preferences
- Better alternatives
- Raise the specificity a little
- Lower the other rule with :where()
- Put third-party CSS in a layer
- !important from JavaScript
- FAQ
!important makes a CSS declaration win over every normal declaration for the same property, no matter how specific their selectors are or where they appear. You add it after the value, before the semicolon:
color: red !important;
It’s a sledgehammer. It fixes the problem in front of you, and often creates the next one, because the only way to beat an !important is another !important. Here’s how it works, when it’s the right call, and what to use instead.
Demo:
ID selector: blue wins over the class
!important: green wins over the ID
Both paragraphs match a red class rule and a blue ID rule. Normally the ID wins, so the first line is blue. The second line also has a class rule with !important, and that beats the ID.
How !important fits into the cascade
When several rules set the same property on an element, the browser picks one in this order:
- Importance:
!importantdeclarations beat normal ones. - Cascade layers: declarations outside
@layerbeat layered ones (reversed for!important, see below). - Specificity:
#idbeats.class, which beatselement. - Order: the rule that comes last wins.
Inline style="" attributes beat all normal stylesheet rules, but an !important in a stylesheet still beats a normal inline style.
How to override an !important rule
Use another !important with a more specific selector, or with the same specificity placed later. That’s exactly why !important spreads: each fix needs a stronger one.
/* Third-party CSS you can't edit */
.btn { background: gray !important; }
/* Same specificity, later in the file: wins */
.btn { background: #1d4ed8 !important; }
/* Or more specific: wins wherever it is */
.header .btn { background: #1d4ed8 !important; }
!important and cascade layers
With @layer, normal declarations in later layers win. For !important it’s the other way around: an !important in an earlier layer beats one in a later layer, and important declarations in any layer beat unlayered important ones. That lets a base layer protect a few rules, like reduced-motion settings, from everything that comes after it.
@layer reset, components;
@layer reset {
/* Protected: wins over !important in "components" */
* { animation-duration: 0.01ms !important; }
}
@layer components {
.spinner { animation-duration: 1s !important; } /* loses */
}
When !important is the right tool
There are a few legitimate uses. Everywhere else, it’s usually a sign of a specificity problem worth fixing properly.
Utility classes that must always apply
A class like .hidden or .sr-only should work no matter what other styles the element has. Tailwind’s important modifier (!hidden) does exactly this.
.hidden {
display: none !important;
}
Overriding inline styles you don't control
Plugins, embeds and email templates often write inline style attributes. A stylesheet rule can only beat those with !important.
/* <div class="widget" style="width: 600px"> from a plugin */
.widget {
width: 100% !important;
}
Respecting user preferences
A global reduced-motion rule should beat every animation on the page, including ones from libraries.
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Better alternatives
If you’re reaching for !important because a rule “won’t apply”, one of these usually fixes it cleanly.
Raise the specificity a little
Add a parent class, or repeat the class (.btn.btn) to bump specificity without changing what the selector matches. And document why, with a CSS comment, so nobody “cleans it up” later.
/* Instead of .btn { color: white !important; } */
.card .btn { color: white; }
/* Same element, higher specificity */
.btn.btn { color: white; }
Lower the other rule with :where()
:where() has zero specificity. Wrap base or library-style selectors in it, and anything you write later overrides them without a fight.
/* Base styles that are easy to override */
:where(.card) a {
color: #1d4ed8;
}
/* Wins, no !important needed */
.promo a {
color: white;
}
Put third-party CSS in a layer
Import frameworks into a cascade layer, and all your unlayered CSS beats them automatically, regardless of specificity.
@import url("bootstrap.css") layer(vendor);
/* Unlayered: beats everything in "vendor" */
.btn { border-radius: 999px; }
!important from JavaScript
element.style.color = 'red !important' doesn’t work: the value is rejected. Use setProperty with a third argument.
el.style.setProperty('color', 'red', 'important');
FAQ
What does !important mean in CSS?
It marks a declaration as important, so it overrides all normal declarations for that property on that element, regardless of specificity and source order.
Is using !important bad practice?
Not always, but usually. It’s fine for utility classes, overriding inline styles you don’t control, and accessibility resets. Used to win specificity battles, it makes CSS harder to maintain.
Does !important work in inline styles?
Yes: style="color: red !important". That’s the strongest normal author style there is; only an !important in a protected cascade layer or a browser/user setting beats it.
Does !important work inside @keyframes?
No. Declarations with !important inside keyframes are ignored.
Where does !important go?
After the value and before the semicolon: margin: 0 !important;. With a space before it, and no space between ! and important by convention.