CSS Portal

Unused CSS Finder

Every line of CSS your browser downloads, parses, and indexes has a cost - even if it never matches a single element on the page. Over time, stylesheets accumulate dead weight: rules left behind after a redesign, utility classes that were copied from a template but never used, component styles for features that were removed, and vendor overrides that no longer apply.

The result is a stylesheet that is larger than it needs to be, slower to parse on low-powered devices, and harder to maintain. CSS Auditor gives you a clear, actionable list of every selector that isn't matching anything in your HTML - so you can trim the fat with confidence.

If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!
Unused CSS Finder

Find your unused CSS rules

Paste your code or enter a URL to scan for CSS selectors that don't match any element in your HTML.

Only same-domain CSS and JS files will be fetched. External resources (fonts, CDN libraries) are skipped. JS files over 500 KB are skipped to avoid fetching large bundles.
HTML
JavaScript (optional)
CSS

Fetching page and stylesheets…

Scan Results
Original size -
Cleaned size -
You save -
Removed CSS 0%
Review before deleting any rules This tool performs static analysis only. It cannot detect CSS classes or IDs that are: injected by JavaScript at runtime · generated dynamically from a database or CMS · added by third-party libraries or frameworks · used in iframes or shadow DOM · applied via classList.add() or template literals. JS scanning covers vanilla JS, jQuery, React, Vue, Alpine.js, Angular, and Svelte - see the About section for exactly which patterns are recognised. Other library APIs and dynamically computed class names are not parsed. Always do a final manual review before removing rules from production code.
Unused Rule Sets
If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!
About Unused CSS Finder

A no-nonsense tool for cleaner stylesheets

How it works

When you provide HTML and CSS - either by pasting code directly or by entering a URL - CSS Auditor parses your stylesheet into individual rule sets, then tests each selector against a DOM built from your HTML using the browser's native querySelectorAll. This means the matching logic is exactly as accurate as a real browser: compound selectors, attribute selectors, child combinators, and complex pseudo-classes all work correctly.

For dynamic classes that only appear at runtime, the tool scans both your JavaScript and HTML source for patterns across several libraries. Vanilla JS: classList, className, setAttribute, dataset. jQuery: addClass, removeClass, toggleClass, attr(), prop(), $() selectors. React: static className, clsx/classnames/cn() calls, template literals. Vue & Alpine.js: :class / v-bind:class / x-bind:class with object, ternary, and string syntax. Angular: [class.foo] and [ngClass]. Svelte: class:foo directives. Detected libraries are shown as a pill in the scan results.

What it handles

  • @media, @supports, @layer, @container - rules inside conditional blocks are tested individually; the block wrapper is preserved in the cleaned output.
  • Native CSS nesting - .parent { .child { } } and &:hover style references are resolved to their fully-qualified selectors before testing.
  • Pseudo-classes - state-based pseudos like :hover, :focus, :checked are handled by testing the structural base selector instead (if the element exists, the rule is kept).
  • Multi-class selectors - class="btn btn-primary" correctly matches .btn, .btn-primary, and .btn.btn-primary independently.
  • Comma lists - h1, h2, .title is split correctly, even when selectors contain commas inside :is() or :not().
  • @keyframes, @font-face, @import - always preserved in output, never flagged as unused.
  • Vendor pseudo-elements - ::-webkit-scrollbar and similar are always kept since browsers throw on querySelectorAll for these.

Known limitations

CSS Auditor performs static analysis only. It scans the HTML and JavaScript you provide at the moment of scanning - it cannot execute your JavaScript, simulate user interactions, or observe what the DOM looks like after a framework has rendered. This means the following patterns may produce false positives (rules flagged as unused that are actually used):

  • Classes generated or injected by a CMS, database, or server-side template at runtime
  • Classes set via computed strings: 'btn-' + variant or template literals with expressions
  • Unsupported library patterns - CSS Modules, styled-components, Emotion, and other CSS-in-JS tools that generate hashed class names at build time are not supported and cannot be statically analysed
  • Styles applied inside iframes, Web Components, or Shadow DOM
  • CSS-in-JS libraries that generate class names at build or runtime
  • Classes added by third-party scripts, analytics, chat widgets, or ad networks
  • Framework-generated class names (e.g. Vue scoped styles, Angular encapsulation)

Always treat the results as a starting point for review, not an automatic delete list. The cleaned output is yours to inspect and verify before using in production.

Frequently Asked Questions

What is an unused CSS finder?

An unused CSS finder is a tool that compares your stylesheet against your HTML and identifies CSS selectors that do not match any element on the page. Every selector that is downloaded and parsed by the browser carries a performance cost, even if it never applies to anything. Over time stylesheets accumulate dead weight - rules left behind after redesigns, utility classes copied from templates, and component styles for features that were removed. An unused CSS finder gives you a clear list of those rules so you can safely remove them and reduce your stylesheet size.

How does the Unused CSS Finder work?

When you provide HTML and CSS - either by pasting code directly or by entering a URL - the tool parses your stylesheet into individual rule sets, then tests each selector against a DOM built from your HTML using the browser's native querySelectorAll. This means the matching logic is exactly as accurate as a real browser: compound selectors, attribute selectors, child combinators, and complex pseudo-classes all work correctly. For classes that appear at runtime, the tool also scans your JavaScript for patterns used by Vanilla JS, jQuery, React, Vue, Alpine.js, Angular, and Svelte.

Is my code sent anywhere?

No. All analysis runs entirely in your browser. When using Paste Code mode, your HTML, CSS, and JavaScript never leave your machine. When using Scan URL mode, a PHP proxy on the same server fetches the page - the code still does not go to any third-party service.

Why is a rule showing as unused when I know it is used?

The most common reason is that the class is added dynamically by JavaScript after the page loads, or generated server-side by a CMS or database. If the class name appears in your JavaScript, paste the JS into the JavaScript field - the token scanner will detect it. If it comes from a database, CMS, or a CSS-in-JS library that generates hashed class names at build time (such as CSS Modules, styled-components, or Emotion), it cannot be detected statically and the rule will be incorrectly flagged as unused. Always treat results as a starting point for review rather than an automatic delete list.

Can I use this with Tailwind, Bootstrap, or other frameworks?

Yes, but with caution. Framework utility classes are often generated or applied dynamically. Tailwind in particular generates classes based on a content scan at build time - if you paste the compiled CSS alongside your HTML, the auditor will correctly show which compiled classes are not present in that HTML. However, if classes are applied at runtime or generated by a server-side template, they will not appear in the HTML you paste and may be incorrectly flagged. Bootstrap works well in most cases since its classes are typically written directly into HTML markup.

Does the cleaned output minify the CSS?

No - the output preserves your original formatting, property values, and comments. The goal is a clean, readable stylesheet you can diff against your original, not a minified production bundle. If you want to minify the result afterwards, run it through the CSS formatter and minifier.

Can I scan a page that requires login?

Not directly via the URL scanner - the PHP proxy fetches pages as an unauthenticated request, so pages behind a login wall will not load correctly. For authenticated pages, log in using your browser, use DevTools to copy the full rendered HTML and the linked stylesheet contents, then paste them into the Paste Code mode instead.

What CSS features does the tool handle?

The tool correctly handles @media, @supports, @layer, and @container - rules inside conditional blocks are tested individually and the block wrapper is preserved in the cleaned output. Native CSS nesting (.parent { .child { } } and &:hover style references) is resolved to fully-qualified selectors before testing. State-based pseudo-classes like :hover, :focus, and :checked are handled by testing the structural base selector. @keyframes, @font-face, and @import are always preserved and never flagged as unused. Vendor pseudo-elements like ::-webkit-scrollbar are always kept since browsers throw errors on querySelectorAll for these.

What are the limitations of static CSS analysis?

Static analysis can only work with the HTML, CSS, and JavaScript you provide at the moment of scanning - it cannot execute JavaScript, simulate user interactions, or observe what the DOM looks like after a framework has rendered. This means classes generated or injected by a CMS, computed strings like 'btn-' + variant, styles applied inside iframes or Shadow DOM, and classes added by third-party scripts cannot be detected. CSS-in-JS libraries such as styled-components and Emotion that generate hashed class names at build or runtime are also not supported. Always do a final manual review before removing any rules from production code.

How does URL scanning work and what gets fetched?

When scanning a URL, the tool fetches the page and its stylesheets server-side using a PHP proxy. This sidesteps browser CORS restrictions without relying on any external service. Only resources on the same domain as the scanned page are fetched - this applies to both CSS (<link rel="stylesheet"> and <style> tags) and JavaScript (<script src> and inline <script> blocks). External resources such as Google Fonts, CDN-hosted libraries, and third-party widget CSS are intentionally skipped. JavaScript files over 500 KB are also skipped to avoid processing large minified bundles that are unlikely to contain your own class names.

Why should I remove unused CSS?

Every line of CSS your browser downloads, parses, and indexes has a cost even if it never matches a single element. Removing unused CSS reduces your stylesheet file size, which improves page load times - particularly on mobile devices and slower connections. It also reduces the time the browser spends parsing and building the CSSOM, which contributes to faster rendering and better Core Web Vitals scores. Beyond performance, a leaner stylesheet is significantly easier to maintain, debug, and hand off to other developers.

Is it safe to delete all the rules the tool flags as unused?

Not necessarily - you should always review the results before deleting anything. The tool performs static analysis only, which means it cannot detect classes added by JavaScript at runtime, generated by a server-side template, or applied by third-party libraries. A rule flagged as unused may still be needed in contexts the tool could not see. Use the results as a guided checklist: verify each flagged rule in your codebase and test thoroughly in a staging environment before removing anything from production.

If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!