When two CSS declarations compete, the browser uses the cascade to choose a value. Selector specificity is one part of that process. It does not make a declaration win across every origin, importance level, or cascade layer.

Start with a visible conflict

Compare competing rulesLink

HTML and CSS

HTML

<p class="note">Which rule sets this color?</p>

CSS

p {
  color: #172334;
}
.note {
  color: #164eae;
}
p {
  color: #8a174b;
}

Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.

The text is blue. The class selector is more specific than the type selector, so the later p rule does not win. Change the last selector to .note and the equal-specificity rule that appears later wins.

How the browser chooses

First, a rule must match the element and apply in the current conditions, such as a media query. The browser then compares origin and importance, including cascade layers, before selector specificity. Scoping proximity can decide an otherwise tied match inside @scope; source order is the final tie-breaker.

Normal author styles typically beat normal browser defaults. User styles marked important can beat author important styles, which matters for accessibility preferences. Animations and transitions have their own positions in the cascade; a transition can temporarily override even an important value.

Read specificity as columns

IDs contribute to the first column, classes, attributes and most pseudo-classes to the second, and type selectors and pseudo-elements to the third. Compare the columns from left to right. Ten classes do not turn into one ID.

  • p has specificity 0-0-1.
  • .note has 0-1-0.
  • #intro has 1-0-0.
  • .panel p has 0-1-1.

:where() always contributes zero specificity, including its arguments. :is(), :not(), and :has() take specificity from their most specific argument. Combinators do not add specificity.

Inline styles outrank ordinary stylesheet declarations at the same author origin and normal importance. !important changes importance, not specificity; it is not a way to add another selector column.

Selector matching

Use a class to identify a component. .panel > p matches its direct paragraph children, while .panel p also matches paragraphs nested deeper. Child combinators make that difference explicit.

:focus-within matches a component while it or a descendant has focus. :focus-visible can style the focused control when the browser decides that a visible indicator is needed. Keep the native focus outline or provide an equally clear replacement.

Layers make overrides predictable

An explicit layer orderLink

HTML and CSS

HTML

<p id="notice" class="notice">
  The components layer wins for these normal rules.
</p>

CSS

@layer base, components;
@layer base {
  #notice {
    color: #8a174b;
  }
}
@layer components {
  .notice {
    color: #164eae;
  }
}

Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.

The later layer’s normal declaration wins before specificity is compared. Normal declarations outside named layers outrank normal declarations inside them. Important declarations reverse the layer order; avoid mixing important declarations into a layering strategy until you understand that reversal.

Inheritance is a different step

If the cascade does not give an element a value for an inherited property, it can use its parent’s computed value. color and font-family commonly inherit. margin does not.

inherit explicitly uses the parent’s value. initial uses the property’s initial value, which may differ from a browser’s default stylesheet. unset chooses inheritance for inherited properties and the initial value for others. revert rolls back the current origin; revert-layer rolls back the current cascade layer.

Debug a rule that loses

Inspect the element’s Styles panel. Check that the selector matched, the value is valid, the relevant media query applies, and the rule is not crossed out. Then check layers and importance before increasing specificity. Finally inspect the computed value and any inherited values.

A declaration can win and still have no visible effect if its layout prerequisites are absent. For example, justify-items does not align flex items.

Sources

MDN: cascade and MDN: specificity cover the order and selector calculations.