Agent Wranglers

Recommended

Remove selectors that match nothing

Fail the build when a class or attribute selector in the stylesheets matches no element in any built page. The only exceptions sit on one list of states and classes that scripts add.

How to do it

Dead CSS makes every later change slower, because nobody dares delete what they cannot trace. Collect every class used in the built HTML and the templates, and compare them with the selectors. Keep the exception list in one file and give each entry its reason. The check that one class styles one kind of element is in Give every module its own class names.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

JavaScript example

import { readFileSync, readdirSync } from 'node:fs';
const ALLOWED_UNUSED = new Set(['basket-toast']); // added by basket.js after a purchase
const pages = readdirSync('dist').filter(f => f.endsWith('.html')).map(f => readFileSync(`dist/${f}`, 'utf8')).join('\n');
const used = new Set([...pages.matchAll(/class="([^"]+)"/g)].flatMap(([, list]) => list.split(/\s+/)));
const styled = new Set([...readFileSync('dist/main.css', 'utf8').matchAll(/\.([a-z][\w-]*)/g)].map(([, name]) => name));
const unused = [...styled].filter(name => !used.has(name) && !ALLOWED_UNUSED.has(name));
unused.forEach(name => console.log(`FAIL .${name} matches no element`));
process.exit(unused.length ? 1 : 0);

Python example

import pathlib, re, sys
ALLOWED_UNUSED = {"basket-toast"}  # added by basket.js after a purchase
pages = "\n".join(p.read_text() for p in pathlib.Path("dist").glob("*.html"))
used = {name for group in re.findall(r'class="([^"]+)"', pages) for name in group.split()}
styled = set(re.findall(r"\.([a-z][\w-]*)", pathlib.Path("dist/main.css").read_text()))
unused = sorted(styled - used - ALLOWED_UNUSED)
for name in unused:
    print(f"FAIL .{name} matches no element")
sys.exit(1 if unused else 0)

How to check

The build reports 0 classes that appear in the stylesheets but in no built page and not on the exception list. Adding .unused-test { } to a component file stops the build.

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/html-css/checks-in-code/unused-selectors">Agent Wranglers HTML and CSS playbook</a>. In code you write, add a comment next to it with the same link.