What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
CSS specificity is a tie-breaker in the cascade, not a universal strength score. The browser considers earlier cascade rules—such as whether a rule applies, its origin, importance, and layer—before comparing selector specificity. When specificity does decide the winner, compare three columns from left to right: IDs, class-like selectors, then types.
Where specificity fits in the cascade
Specificity only compares declarations that remain in contention after earlier cascade criteria have been considered. A selector can look more specific and still lose because its declaration is less important, comes from a lower-precedence origin or layer, or does not apply to the element. After specificity, scope proximity and then source order can resolve a remaining tie. See MDN’s introduction to the CSS cascade.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
CSS Pocket Reference: Visual Presentation for the Web | $19.93 | Buy on Amazon |
| 2 |
|
Pocket Ref | $12.95 | Buy on Amazon |
| 3 |
|
CSS Pocket Reference: Quick Syntax, Selectors, Properties, Flexbox, Grid, and Responsive Design | $11.90 | Buy on Amazon |
| 4 |
|
CSS Pocket Reference: Visual Presentation for the Web | $6.16 | Buy on Amazon |
| 5 |
|
CSS Pocket Reference | $7.78 | Buy on Amazon |
A useful diagnostic sequence is: check whether the rule applies, compare origin and importance, compare layer precedence, then specificity, scope proximity, and source order. The full ordering has details beyond this summary; the key is not to start by counting selector parts.
How to calculate specificity
Write specificity as three columns, often called ID-CLASS-TYPE. Compare the columns from left to right. This is lexicographic comparison, not ordinary arithmetic: do not add the values into a total or read them as a decimal number.
#1 Best Overall
- ID column: ID selectors such as
#app. - Class-like column: class selectors, attribute selectors, and pseudo-classes, such as
.notice,[type="warning"], and:hover. - Type column: type selectors and pseudo-elements, such as
pand::before.
Combinators—including descendant whitespace, >, +, and ~—and the universal selector * add no weight. The rules and examples below follow MDN’s specificity guide and the Selectors Level 4 specification.
| Selector | Specificity | Why |
|---|---|---|
#app .notice[type="warning"] p::before |
1-2-2 |
One ID; one class and one attribute; one type and one pseudo-element. |
.card p |
0-1-1 |
One class and one type. |
#card p |
1-0-1 |
One ID and one type; its ID column outranks the class column in .card p. |
html body main input |
0-0-4 |
Four types. |
:root input |
0-1-1 |
:root is a pseudo-class, so its class-like column is compared before the type column. |
Thus :root input outranks html body main input on specificity, despite having fewer selector components. For a comma-separated selector list, each matching branch has its own specificity; the branch that matches the element determines the specificity for that match. Do not add the branches together.
Modern pseudo-classes that change the calculation
:is(), :not(), and :has()
These pseudo-classes do not add a fixed pseudo-class weight of their own. Instead, their specificity is based on the most-specific selector in their argument list—even if a less-specific branch is the one that matches. For example, :is(.notice, #app) p has specificity 1-0-1: the #app argument supplies the ID column, and p supplies the type column. An ID tucked into one of these argument lists can therefore make a selector unexpectedly difficult to override.
Rank #2
- Author: Thomas Glover
- 864 pages
- 3.2" x 5.4", softbound
- (Also available in Desk Size item 2072)
:where()
:where() and all of its arguments contribute zero specificity. For example, :where(#app) p has specificity 0-0-1, not 1-0-1. This is useful for scoped defaults that should remain easy for application or downstream styles to override.
Recommended Free Tools
For the formal selector rules, consult the Selectors Level 4 specification and MDN’s specificity reference.
How cascade layers affect a specificity conflict
Layers set precedence between groups of declarations; they do not change a selector’s specificity. Within the same origin and importance, normal declarations in a later layer beat those in an earlier layer. Normal declarations outside explicit layers outrank normal declarations inside them. For important declarations, layer ordering reverses. MDN explains the practical ordering in its cascade layers guide; the behavior is specified in CSS Cascading and Inheritance Level 5.
Rank #3
You can use layers to establish intended precedence among resets, third-party styles, components, themes, and overrides without escalating selectors. For example, declare the order once, then place related rules in the appropriate layer:
@layer reset, vendor, components, theme, overrides;
@layer vendor {
.button { color: black; }
}
@layer overrides {
.button { color: rebeccapurple; }
}
For normal declarations, the later overrides layer wins here even though both selectors have the same specificity. Keep the relevant declarations in layers if you want that layer ordering to govern their conflict; an unlayered normal rule outranks layered normal rules in the same origin.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsWhy a more-specific rule can lose
- An earlier cascade criterion decides the result. Importance, origin, or layer precedence is considered before specificity. A higher-specificity declaration can lose if it is in a lower-precedence position.
- The apparent contenders do not actually compete. One selector may not match the same element, the property may differ, or a media, supports, or other conditional rule may not apply.
- A pseudo-class argument adds hidden weight. An ID in
:is(),:not(), or:has()may raise the selector’s specificity. - Inline style is being compared as though it were a selector. Inline styles have special cascade precedence relative to stylesheet rules of the same importance and origin context. They are not a fourth specificity column, and ordinary three-column arithmetic does not let a stylesheet selector beat an inline normal style.
- Specificity ties. Scope proximity can decide a conflict before source order. If scope proximity also ties, later source order may win.
!importantchanges the comparison. It changes cascade priority; it is not a specificity boost. Adding it just to overpower a selector mismatch often makes later maintenance harder.
A practical workflow for diagnosing a losing rule
- Inspect the exact element and property. In browser developer tools, select the element and find the declaration currently applied and the crossed-out declarations. Note each rule’s stylesheet location and selector.
- Verify that both rules can apply. Confirm they target the same element and property, check any conditional rules, and make sure the expected stylesheet loaded.
- Compare the cascade position before counting. Check importance and origin, then layer precedence. A crossed-out declaration with a higher-specificity selector can still lose at this stage.
- Calculate the remaining selectors. Count each selector’s ID, class-like, and type components separately. Inspect
:is(),:not(), and:has()arguments for specificity that may not be obvious from the matching branch. - Resolve a tie in order. Check scope proximity when scopes are involved, then source order.
- Make the smallest maintainable change. Prefer a clear reusable class, a deliberate layer adjustment, or reduced specificity in the original rule over repeatedly appending ancestors or IDs. Use
!importantonly when the priority is intentional and document it where maintainers will see it.
How to avoid specificity problems in a stylesheet
Use classes for reusable component rules
Keep component selectors predictable rather than tying them to long ancestor chains. Extra nesting does not automatically make a stylesheet easier to maintain, and combinators add no specificity. A later override should not require reconstructing the component’s entire DOM path.
Use :where() for low-weight scoping
When a rule needs a scope for clarity but should be easy to override, place that scope inside :where(). This is especially helpful for defaults or styles intended to be customized by consumers.
Set layer order deliberately
Use cascade layers to express which category of normal styles should take precedence. This can resolve conflicts across a reset, vendor stylesheet, component styles, and application overrides without making each selector heavier. Remember the distinct normal and important layer ordering, and account for unlayered normal rules.
Do not escalate selectors reflexively
Adding ancestors, IDs, or !important can solve one immediate conflict while making future overrides more difficult. First identify which cascade stage caused the loss; then change that stage rather than inflating specificity by habit.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Best Value
- Ships from Vermont
Or skip the browser setup
If you need a clean visual capture of a rendered page while reproducing a CSS issue, ScreenshotNeo can return an image or PDF from one GET request. It does not inspect or explain CSS; use browser developer tools for the cascade diagnosis. Example request, using https://stripe.com as the target URL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free.
Frequently Asked Questions
Does adding more parent elements always make a selector stronger?
No. Combinators and the relationships they describe add no specificity; only the selector components in the three columns count.
Can a selector with an ID lose to a selector with many classes?
Not on specificity alone: the ID column is compared first. It can still lose if an earlier cascade criterion, such as importance or layer precedence, decides the conflict.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




