CSS Toolkit
Four everyday CSS jobs in one place: specificity, validation, media queries and variables.
Comma lists become separate rows (a line ending in a comma continues on the next). Pasted CSS works too: declaration blocks are skipped and rules inside @media are read.
Specificity
| Selector | A | B | C |
|---|
A IDs · B classes, attributes, pseudo-classes · C elements, pseudo-elements. Compare A first, then B, then C.
Checked in your browser with css-tree (loaded when you first validate).
Results
Media query
Breakpoint set
Custom properties
Your CSS using the variables
About the CSS Toolkit
A set of CSS helpers that work entirely in your browser. Specificity shows why one rule beats another: paste selectors and see each one's A-B-C score, a breakdown of what counts, and which selector wins — following the rules of the W3C Selectors Level 4 specification, including :is(), :not(), :has(), :where() and :nth-child(… of S).
The Validator checks a stylesheet against the CSS grammars of css-tree (built from MDN's data) and points to the exact line and column of unknown properties, invalid values and syntax errors, with a "did you mean" for typos. Media queries builds @media rules — classic or the newer range syntax — and complete breakpoint sets (Bootstrap and Tailwind presets included), and tells you whether your current window matches. Variables turns design tokens (JSON or name: value lines) into CSS custom properties, or finds the colours repeated in a stylesheet and replaces them with var().
How to use it
- Pick a tab: Specificity, Validator, Media queries or Variables.
- Specificity: paste one selector per line, or whole CSS rules (comma lists are split and declaration blocks skipped). The strongest selector is marked, and each row shows what every part adds.
- Validator: paste or open a .css file. Problems appear with line numbers; select one to jump to it in the editor.
- Media queries: set widths and preferences, choose classic or range syntax, then copy the rule — or generate a full breakpoint set.
- Variables: paste tokens to get a
:root { … }block, or switch to Extract colours to turn repeated colours into custom properties.
Examples
#nav a .menu .item a:hover :is(.menu, #nav) a
#nav a → 1-0-1 .menu .item a:hover → 0-3-1 :is(.menu, #nav) a → 1-0-1
An ID (A) beats any number of classes (B), so #nav a and :is(.menu, #nav) a outrank the four-part selector; between those two equal scores, the rule that comes later in the CSS wins.
Min width 768px · Max width 1024px
Classic: @media (min-width: 768px) and (max-width: 1023.98px) Range: @media (768px <= width < 1024px)
The classic form subtracts 0.02px so that it does not overlap a rule starting at 1024px — the technique Bootstrap documents for its breakpoints.
{"color": {"primary": "#2563eb", "primaryHover": "#1d4ed8"}}:root {
--color-primary: #2563eb;
--color-primary-hover: #1d4ed8;
}Common uses
- Debugging why a style does not apply (a more specific selector elsewhere wins).
- Catching typos such as
colr:ordisplay: flexxbefore they reach production. - Writing responsive breakpoints, dark-mode and reduced-motion queries.
- Converting a design system's tokens into CSS variables, and refactoring hard-coded colours into a palette.
How specificity is counted
Specificity is three numbers compared left to right: A counts ID selectors (#id); B counts classes (.class), attribute selectors ([type=text]) and pseudo-classes (:hover); C counts type selectors (div) and pseudo-elements (::before). The universal selector * and combinators count nothing.
Special cases from Selectors Level 4 §15 (Working Draft): :is(), :not() and :has() count as their most specific argument; :where() counts zero; :nth-child(An+B of S) counts one pseudo-class plus its most specific S. Following CSS Scoping, :host() counts a pseudo-class plus its argument and ::slotted() a pseudo-element plus its argument. Legacy one-colon pseudo-elements such as :before count as pseudo-elements. Inline style attributes and !important are outside specificity and beat it.
What the validator checks
It parses the stylesheet and matches every declaration against the property grammars bundled with css-tree (MIT, based on MDN's mdn-data), reporting syntax errors, unknown properties and at-rules, values that do not fit the grammar, empty rules and properties set twice in one rule. Descriptors inside at-rules — src and font-display in @font-face, size in @page, syntax in @property — are checked against that at-rule's own grammar. Values that use var() cannot be checked until the variables are known, so they are counted but skipped, and custom properties (--name) accept any value by definition.
Design token formats
Paste JSON, or one name: value per line (--name, SCSS $name and Less @name lines work too). Nested JSON groups are joined with hyphens, so {"color": {"primaryHover": "#1d4ed8"}} becomes --color-primary-hover.
- Design Tokens Format Module 2025.10 (Design Tokens Community Group, final report):
$valueand$type, dimension and duration objects ({"value": 0.5, "unit": "rem"}→0.5rem), colour objects (sRGB → hex orrgb(), other colour spaces →oklch(),hsl(),color(display-p3 …)and so on), font-family and cubic-bezier arrays, shadow, border and transition composites, and$roottokens. - Style Dictionary and Tokens Studio files that keep the value under
value. - References such as
{color.blue}or{"$ref": "#/color/blue"}becomevar(--color-blue), so the custom properties keep pointing at each other.
Composite tokens that need several CSS properties, such as typography and gradients, are skipped and listed.
Media query notes
The range syntax — (width >= 48rem) — works in Chrome and Edge 104+, Firefox 102+ and Safari 16.4+ (MDN browser-compat-data); use the classic min-width form if you support older browsers. In media queries, em and rem are relative to the browser's default font size (16px unless the user changed it), which is why many frameworks use them for breakpoints. Presets: Bootstrap 5.3 (576, 768, 992, 1200, 1400px) and Tailwind CSS 4 (40, 48, 64, 80, 96rem).
Limitations
- No autoprefixer: adding vendor prefixes correctly needs current browser-support data (Browserslist and caniuse), which this page does not include. Most modern properties no longer need prefixes.
- The validator follows css-tree's grammars; a property added to browsers very recently may be reported as unknown. It does not check selectors, browser support or cascade conflicts.
- Nested rules (CSS Nesting) are checked when they start with
&; a nested rule written without it, such ash2 { … }inside a rule, is valid CSS but is skipped with a note. - Colour extraction handles hex and colour functions (rgb, hsl, oklch…), not named colours such as
red, and does not touch custom-property declarations. - Specificity for
&(CSS nesting) depends on the parent rule, which a single selector does not contain, so it is counted as zero with a note.
Privacy
Everything happens in your browser. What you enter or open here is not uploaded or stored by MySmartCoPilot.
Frequently asked questions
Why does my CSS rule not apply?
Usually another rule that matches the same element has higher specificity, or the same specificity and comes later. Paste both selectors into Specificity: the higher A-B-C wins, comparing A first, then B, then C. !important and inline styles override specificity altogether.
Do 11 classes beat one ID?
No. Specificity is not a single number: A, B and C are compared in order, so #id (1-0-0) beats .a.b.c.d.e.f.g.h.i.j.k (0-11-0).
Is this the same as the W3C CSS Validator?
It is a different, offline checker. It matches values against css-tree's grammars, which follow MDN's data closely and know most modern properties. For a second opinion you can still use the W3C service, which sends your CSS to its server.
Should I use min-width or the range syntax?
Both work in current browsers. The range syntax is shorter and has a true “less than”, so ranges cannot overlap; the classic syntax works in older browsers too. The tool writes either.
Can it add vendor prefixes (-webkit-, -moz-)?
No — see the limitations. Prefixing correctly depends on which browsers you support and on up-to-date support data; a build tool such as Autoprefixer with your Browserslist settings is the reliable way.