GAP·MAP
← all breakdowns
CSS CascadeSpecificityCascade LayersScopesenior level

How the CSS Cascade Picks a Winner

the question

Several CSS declarations set the same property on an element. How does the browser decide which one wins, including origin, layers, `!important`, specificity, scope, and source order?

what they're testing: The interviewer is testing whether you can debug style conflicts by following the cascade in the right order instead of reaching for stronger selectors.

a strong answer

When declarations set the same property, start by discarding rules that do not match or whose conditions do not apply. Then compare origin and importance, not selector weight. For normal declarations, author styles beat user styles, which beat user-agent styles; for important declarations, that order reverses. Keyframe animations outrank normal declarations, important declarations outrank animations, and an active transition outranks everything.

Within the winning origin and importance bucket, layers come next. Normal unlayered author styles beat layered styles, and later layers beat earlier ones. Important styles reverse both relationships: layered beats unlayered, and earlier layers beat later ones. A normal inline style also outranks normal author stylesheet rules; an important inline style outranks other important author rules.

If declarations still compete, compare specificity as counts of IDs, class-like selectors, and type-like selectors, from left to right. A higher earlier column wins; specificity is not a decimal score. Equal specificity goes to the rule with the fewest hops to its @scope root, then to the declaration that appears last. So “the most specific selector wins” is only useful after the earlier cascade gates are equal.

Why it lands

  • Starts with the cascade order rather than treating specificity as the whole algorithm.
  • Separates `!important` from selector specificity.
  • Explains the reversed ordering for important origins and layers.
  • Ends with a practical rule for scope and source-order ties.

Where people slip

  • “The selector with the highest specificity always wins.” Layers and origin can settle the result first.
  • “`!important` adds the highest specificity.” It changes cascade precedence; it is not selector weight.
  • “The last declaration wins.” Source order is only the final tie-breaker.
  • “A later layer always wins.” Important declarations reverse the layer order.

If they push further

How is selector specificity compared?

Count ID, class-like, and type-like selector components, then compare those columns from left to right. Many type selectors cannot outweigh one class selector.

Why does `!important` reverse origin and layer order?

Reversing origins lets important user styles override author styles, while reversing layers lets early guardrail layers resist later overrides. Specificity still breaks ties within the winning bucket.

How would you debug a declaration that is crossed out in DevTools?

Check its origin and importance first, then its layer. Compare specificity, scope proximity, and source order only against declarations still competing in that same bucket.

Sources

Now answer it yourself.

Reading a strong answer is easy. Producing one under pressure is the skill the interview tests. Gapmap grades your answer against the same bar an interviewer would.

was this useful?

beta

The interviewer part is in the works.

The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.