Command Palette

Search for a command to run...

Hectal
PHASE 2Beginner ~20 min· topic 4 of 5

Topic 2.4

!important and How to Avoid Needing It

In one line

Adding !important to a declaration moves it into a stronger group of the cascade, above every normal declaration whatever its specificity; it is a last resort that fixes today's bug and makes tomorrow's harder.

Think of it like this

A teacher who writes "URGENT" on every note. The first urgent note gets attention. When every note says URGENT, the word means nothing, and the only way to stand out is "SUPER URGENT". !important is CSS's URGENT stamp, and stylesheets that use it often end up in exactly that race.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

!important
A flag after a value that puts the declaration in a stronger cascade group than normal declarations.
Normal declaration
A declaration without !important.
Important declaration
A declaration ending in !important.
User stylesheet
Styles a person sets for every website they visit, often for accessibility, like larger text.
Override
To replace a value set by another rule with your own.
Utility class
A small class that does one job, like .hidden or .text-center.

Step by step

01Write it on one declaration

The flag goes after the value and before the semicolon. In this rule, only color is important. font-weight is a normal declaration that can lose as usual.

style.csswhole filecss
.note {
  color: seagreen !important;
  font-weight: bold;
}

02See it jump over specificity

With #tip { color: crimson; } in the same stylesheet, a paragraph with id="tip" and class="note" is still seagreen. The cascade decided at step 1 (importance) and never compared the selectors.

03Watch two importants fight

Add #tip { color: crimson !important; }. Now both are important, so the cascade continues to specificity, and the ID wins again. You are back where you started, with two flags instead of none.

style.csswhole filecss
.note { color: seagreen !important; }  /* important, (0, 1, 0) */
#tip  { color: crimson !important; }   /* important, (1, 0, 0): wins */
Watch two importants fightdiagram
Rendering diagram…

04Fix the cause instead

Ask why the rule is losing. Usually a selector is too strong or a rule is in the wrong place. Lower the strong selector, or add one class to yours, or move it later.

style.csswhole filecss
/* before */
#sidebar a { color: gray; }
.cta { color: white !important; }

/* after */
.sidebar a { color: gray; }        /* (0, 1, 1) */
.sidebar .cta { color: white; }    /* (0, 2, 0) wins, no flag */

05Keep !important for the few real cases

A utility like .hidden should hide an element whatever other rules say, so the flag matches the intent. Overriding a third-party widget's inline style attribute is another case: from a stylesheet, only !important beats an inline style.

utilities.csswhole filecss
.hidden { display: none !important; }

/* a widget writes style="width: 600px" and you can't change it */
.chat-widget { width: 100% !important; }

Try it yourself

  1. 1

    Remove a flag and predict

    In the first example, delete !important from .safe. Predict each paragraph's colour before you run (crimson, purple, darkorange). The ID and the inline style win again.

  2. 2

    Try to beat the inline important

    In the first example, add #one, p.safe.safe.safe { color: navy !important; }. Paragraph 3 stays darkorange: nothing in a stylesheet beats an important inline style.

  3. 3

    Win without the flag

    In the third example, remove !important from .hidden and move the .hidden rule above .card. The hidden card reappears. Move it below .card again: it hides, with no flag, because equal specificity means the later rule wins. Now you see why utilities use the flag: they shouldn't depend on order.

Code & diagrams

!important beats IDs and inline styles New tab

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Paragraph 1: seagreen
Paragraph 2: seagreen
Paragraph 3: darkorange
When two !important declarations fight New tab

`el.style.color = "navy"` would lose to `.note`'s important rule. `setProperty` with `"important"` writes an important inline style, which wins.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Inline priority: important
Paragraph 1: crimson
Paragraph 2: steelblue
Paragraph 3: navy
A legitimate use: a utility that must always win New tab

Preview

Press Run to see the page.

Console

Nothing logged yet.

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

The !important race

A theme sets .btn { background: blue !important; }. To make one button red you write .btn-danger { background: red; }.

terminal
$ the page shows
── what you'll see ──
The danger button stays blue. DevTools shows `background: red` crossed out.

Break #2

!important inside @keyframes

Write @keyframes pulse { to { opacity: 0.2 !important; } } to make an animation step stronger.

terminal
$ the page shows
── what you'll see ──
The opacity no longer animates; the element stays at full opacity.

Myth vs fact

Myth

!important makes a whole rule important.

Fact

It applies only to the one declaration it is written on.

Myth

Nothing can beat !important.

Fact

Another important declaration with a stronger inline/layer/specificity position beats it, an important inline style beats all stylesheet rules, important user and user-agent styles beat it, and running transitions beat everything.

Myth

!important is always bad practice.

Fact

It's right for utility classes that must always win, for overriding inline styles you don't control, and in user and accessibility stylesheets. It's wrong as a quick fix for a selector fight.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    The origin flip for important declarations is a user-protection rule from CSS2. Combined with cascade layers, the spec applies the same flip to layers: important declarations in earlier layers win (Topic 2.5), so a reset layer can lock values that later layers can't touch.

  • ▸

    From JavaScript, el.style.color = "red !important" is invalid and silently ignored. Use el.style.setProperty("color", "red", "important") and read the flag back with getPropertyPriority().

  • ▸

    Some frameworks offer an "important" switch (Tailwind's ! prefix or its important config option) to make utilities beat legacy CSS. It's a migration tool; cascade layers are the cleaner long-term answer.

  • ▸

    A good lint rule (for example Stylelint's declaration-no-important) flags new !important uses in code review, with exceptions for a utilities file.

Remember this

  1. 1

    !important is written after a value, before the semicolon: color: red !important;. It applies to that one declaration only, not to the whole rule. The ! is not "not": it is simply the marker that starts the flag. Spaces are allowed (! important), but nobody writes it that way.

  2. 2

    In the cascade (Topic 2.1), importance is checked in the first step, together with origin. Every important author declaration beats every normal author declaration, whatever the selectors. .note { color: green !important } beats #tip { color: red } and even an inline style="color: red" attribute.

  3. 3

    When two important declarations compete, the cascade carries on as usual: inline style, layers, specificity, then order of appearance. So #tip { color: red !important } beats .note { color: green !important }. An inline style="color: red !important" beats every important rule in your stylesheet, and is the strongest thing an author can write.

  4. 4

    For important declarations, the origin order flips: important user-agent beats important user, which beats important author. This is deliberate. A person who needs large text or high contrast can write an important user style, and no website can override it. The flip exists to protect users, not to help authors win fights.

  5. 5

    Why it causes trouble: !important doesn't fix the cause (a selector that is too strong, or rules in the wrong order). It jumps over it. The next person who needs to override that declaration must also use !important, with a stronger selector. Soon nothing can be changed safely. In DevTools, a stylesheet full of !important shows the cascade has stopped working.

  6. 6

    How to avoid needing it: keep specificity low (classes, not IDs), put rules in a sensible order (base styles first, components, then specific overrides), use :where() for easy-to-override defaults, and use cascade layers (Topic 2.5) to rank whole groups of rules. Legitimate uses remain: utility classes that must always win (.hidden { display: none !important; }), overriding inline styles you don't control (from a third-party widget), and user or accessibility stylesheets.

Explain it without notes

01

Where does !important act in the cascade, and what does it beat?

02

Two declarations are both !important. How is the winner chosen?

03

Why does the origin order flip for important declarations?

04

Give three ways to fix a losing rule without !important, and two cases where !important is the right tool.

Practice

01

The CSS is #nav a { color: gray; } and .active { color: tomato; }; the active link in #nav stays gray. Fix it two ways without !important.

02

Write a .visually-hidden utility that is always hidden from sight (but still readable by screen readers) and can't be broken by other rules setting position or width.

Trade-offs

  • ↔

    !important is the fastest fix for one bug, but every use raises the cost of the next override; fixing specificity or using layers takes longer now and keeps the stylesheet changeable.

Done when you can

  • I can say where !important acts in the cascade.

  • I can predict the winner when two important declarations compete.

  • I can explain why important user styles beat important author styles.

  • I can fix a losing rule without !important.

  • I can name legitimate uses of !important.