Developer · CSS

Unused CSS selector checker.

Paste a page's HTML and its CSS to see which selectors match nothing, and roughly how many bytes they take. Runs in your browser; nothing is uploaded.

Advertisement

Input

The rendered markup of the page, including every state you want counted (open menus, modals, error messages).
Plain CSS. Rules inside @media, @supports, @layer and @container are checked; @keyframes and @font-face are skipped.

Result

Paste HTML and CSS, then press Check selectors.

How selectors are tested

Your HTML is parsed with the browser's DOMParser. Each selector from your CSS is then passed to querySelector(). Per the DOM Standard, that method returns the first element matching the selector, or null if there is none. A selector that returns null matches nothing in the HTML you pasted, so it is reported as unused.

Cannot verify statically: whether a:hover, input:focus or a:visited applies depends on what the user is doing, and pseudo-elements such as ::before or ::placeholder depend on rendering, not on the markup. Selectors Level 4 defines the user-action and link-history pseudo-classes as states of an element. The tool strips these, tests the part that remains (a, input), and if that part exists reports the selector as "cannot verify statically" instead of unused. If the remaining part matches nothing, no element could ever be in that state, so the selector is reported as unused. A state pseudo-class inside :not(), :is() or :has() is also reported as cannot verify.

Estimated bytes: the UTF-8 size of the CSS as you pasted it, with comments removed. When every selector in a rule is unused, the whole rule counts (selectors, braces and declarations). When only some are unused, only those selectors and their commas count. It is a source-size estimate before minification and gzip, and the wrapping @media line is not counted.

What this cannot see: classes, ids, attributes and elements that JavaScript adds after load, content injected later, and any page state not present in the HTML you paste. A selector marked unused may be live in a state you did not paste. Check before deleting.

Sources: DOM Standard, ParentNode.querySelector(); Selectors Level 4 (pseudo-elements, section 3; link and target pseudo-classes, section 8; user action pseudo-classes, section 9).

Frequently asked questions

Why is my selector marked unused when the site uses it?

The tool only sees the HTML you paste. If a script adds the class later, such as an open menu or a modal state, paste the HTML with that state applied or leave the selector alone.

What does "could not test" mean?

The browser rejected the selector as invalid or unsupported, so querySelector() threw an error. Vendor-specific or very new syntax can land here. Those rules are not counted as unused.

Does it handle nested CSS or Sass?

No. Nested rules and preprocessor syntax are not expanded. Paste compiled CSS.

Is my code sent anywhere?

No. Parsing and matching happen in your browser tab. The pasted HTML is parsed into a detached document, so its scripts do not run.

Static check only

This tool reports selectors that match nothing in the HTML you pasted. It cannot see JavaScript-added classes or states, so review the list before deleting any CSS.

Advertisement
Advertisement
Listening…