CSS !important: What It Does and When to Use It

By Marko Denic
Contents
  1. How !important fits into the cascade
  2. How to override an !important rule
  3. !important and cascade layers
  4. When !important is the right tool
  5. Utility classes that must always apply
  6. Overriding inline styles you don't control
  7. Respecting user preferences
  8. Better alternatives
  9. Raise the specificity a little
  10. Lower the other rule with :where()
  11. Put third-party CSS in a layer
  12. !important from JavaScript
  13. 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:

  1. Importance: !important declarations beat normal ones.
  2. Cascade layers: declarations outside @layer beat layered ones (reversed for !important, see below).
  3. Specificity: #id beats .class, which beats element.
  4. 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.

css
/* 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.

css
@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.

css
.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.

css
/* <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.

css
@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.

css
/* 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.

css
/* 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.

css
@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.

javascript
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.