CSS Free, no sign-up

CSS specificity calculator

Type CSS selectors one per line — the calculator splits each one into parts, works out its (a,b,c) specificity and shows which rule wins.

Result
Ready-made CSS
/* #nav .item a  →  (1,1,1) */
/* .nav .item a:hover  →  (0,3,1) */
/* nav ul li a  →  (0,0,4) */
/* winner: #nav .item a  →  (1,1,1) */

How to use it

  1. Type one selector per line (up to 10 lines) or load an example.
  2. Read the color-coded breakdown: red marks a (IDs), blue marks b (classes, attributes, pseudo-classes) and green marks c (types, pseudo-elements).
  3. Compare the (a,b,c) badges: a is compared first, then b, then c. The selector ranked first wins.
  4. If the weights are identical, the rule written later in the CSS wins. !important, inline styles and @layer are decided separately.

How it works

Three numbers: (a,b,c)

Specificity has three columns. a counts ID selectors (#id), b counts classes (.class), attributes ([type]) and pseudo-classes (:hover), and c counts type selectors (div) and pseudo-elements (::before). Columns are compared from left to right: one ID beats any number of classes, and eleven type selectors never beat one class — the columns do not carry over into each other.

#nav .item a        →  (1,1,1)
.nav .item a:hover  →  (0,3,1)
nav ul li a         →  (0,0,4)

What counts and what does not

The universal selector *, combinators (space, >, +, ~) and :where() add 0. An attribute selector such as [id="x"] is still an attribute, not an ID, so it goes into column b. The legacy single-colon pseudo-elements :before, :after, :first-line and :first-letter count as pseudo-elements and go into c.

:is(), :not(), :has() and :where()

:is(), :not() and :has() add nothing themselves but take the specificity of the most specific argument in their list: :is(#a, .b) is (1,0,0). :where() is always zero, which makes it ideal for resets and base styles that must stay easy to override. :nth-child(2n+1 of .x) is a pseudo-class (b) plus the specificity of .x.

Specificity is not the whole cascade

The cascade first looks at origin and !important, then at styles attached to the element (inline), then at @layer layers, and only then compares specificity; source order is the last tiebreaker. That is why style="..." and !important beat a normal rule whatever its selector weight, and a rule in a later layer beats a stronger selector in an earlier one. For !important, the layer order is reversed.

@layer base, components;
@layer base { #page p { color: red; } }
@layer components { p { color: blue; } }
/* components wins: the layer is declared later */

FAQ

Why is my rule ignored although it comes later in the file?

Source order only decides when specificity is equal. Most likely another rule has a stronger selector. Type both selectors into the calculator and compare them, then check for !important, inline styles and @layer.

Does !important change specificity?

No. !important is a separate step of the cascade: an important declaration beats a normal one, and among several important ones specificity and order decide again. Instead of adding !important, it is usually better to simplify the selector or move the styles into an @layer.

Can many classes beat one ID?

No. Column a is compared before b, so even a hundred classes will not beat a single ID: (1,0,0) is stronger than any (0,N,M). On the other hand, (0,2,0) beats (0,1,5).

Does an inherited value take part in the comparison?

No. Any rule that targets the element directly — even one with the * selector and zero specificity — beats a value inherited from the parent.

This topic in the HTML & CSS course

More CSS tools

CSS gradient generator Linear, radial and conic gradients: pick colors, angle and stops, then copy the code. Flexbox generator and playground Try flex properties on a container and its items: direction, alignment, gaps and ready-made CSS. CSS Grid generator Set columns and rows, gaps and alignment, then copy the ready-made grid code. CSS box-shadow generator Pick offset, blur, color and layers for a shadow, then copy the ready-made box-shadow code. Cubic-bezier generator Drag the control points of an easing curve and copy the ready-made CSS transition. SVG animation generator Pick a shape and an effect — get inline SVG and CSS keyframes ready to paste. CSS box model visualizer See content, padding, border and margin as a DevTools-style diagram and copy the CSS. CSS transform generator Move, rotate, scale and skew an element, see its original position and copy the code. CSS clamp() calculator Enter min and max font size and viewport width — get a ready clamp() for fluid typography. Color contrast checker (WCAG) Check text and background contrast against WCAG AA and AAA, and fix a failing pair of colors. CSS clip-path generator Polygons, bevels, arrows and circles: drag control points on the live canvas and copy ready-made CSS. CSS glassmorphism generator Frosted glass effect: backdrop-filter blur, saturation, border highlight and clean CSS. CSS border-radius (Blob) generator Organic shapes and 8-value border-radius: tune horizontal and vertical corner radii. CSS Stacking Context & z-index Visualizer Why z-index: 9999 fails! Explore CSS Stacking Contexts in interactive 3D exploded layers with transform, opacity and isolation triggers. CSS aspect-ratio & object-fit Generator Eliminate squished images & CLS layout jumps: live aspect-ratio proportions and interactive object-position focal point. CSS Filters Studio & Generator Photo effects without design tools: blur, contrast, hue-rotate, sepia, and trending Instagram-style presets. OKLCH Color Picker & Palette Generator Perceptually uniform brightness & vibrant Display P3 colors: OKLCH picker, design system scales, and fallbacks. CSS Scroll-driven Animations Generator Scroll-linked animations without JavaScript: animation-timeline scroll() & view(), reading progress bar & reveal on scroll. CSS Container Queries (@container) Generator Beyond viewport media queries: components adapt directly to their parent container width. Live resizer & @container rules.
WhatsApp