fxcss audit
fxcss audit
fxcss audit --patch fix.diff # write the confident fixes as a patch
fxcss audit --strict # exit non-zero if a selector needs attention
fxcss audit --strict-vars # …or if a custom property override is deadUpgrading a theme after Firefox moved on. inspect answers the question one
selector at a time; audit does the whole theme at once. It walks every id and
class your CSS mentions, resolves each against a running Firefox, and shows what
to change — with the real line from your file and the replacement applied:
14 selectors need attention
RENAMED #urlbar-background → .urlbar-background
same name, now a class rather than an id
chrome/parts/headerbar-urlbar.css:52
- #urlbar-background {
+ .urlbar-background {
SIMILAR #appMenu-fullscreen-button → #appMenu-fullscreen-button2 (a guess, not applied)
no exact match; closest live name is #appMenu-fullscreen-button2
chrome/parts/icons.css:198
#appMenu-fullscreen-button {These examples come from findings in a long-running theme. The
…-button2 pattern is how Firefox has been versioning app-menu controls, and it
breaks menu styling silently.
Findings are grouped as follows:
| meaning | |
|---|---|
| RENAMED | The same name exists, but as a class instead of an id, or the reverse. The suggestion is exact. |
| SIMILAR | No exact counterpart, but a close name exists. Usually a Firefox suffix change, or a typo in your CSS. |
| offscreen | Not in any state the live audit produced, but present in the markup this Firefox ships — a dialog, another platform's chrome. Healthy, and the report says which file carries it. |
| unresolved | Nothing close. Listed separately with --all and not counted as a problem — normally an element that only appears in a state fxcss cannot reach, not one that was removed. |
That last distinction is the point. Reporting every unmatched selector as broken would be noise; a theme legitimately styles things that only exist in private windows, on other platforms, or inside popups.
Suggestions are inferred from the live browser, not from a hardcoded list of Firefox versions, so they keep working for releases that came out after this tool did.
--patch writes a unified diff of the RENAMED findings only — the ones where
the replacement is certain. If a replacement would repeat another selector in
the same rule, that occurrence is left out of the patch and the report asks
you to remove the redundant selector manually. Other safe occurrences are
still patched. Review the diff, then git apply. SIMILAR findings are
deliberately excluded: they are usually right, but "usually" is not good enough
to rewrite your CSS unattended.
Custom properties die differently
A selector that stops matching is only half of how a theme goes stale. The
other half is a custom property Firefox stops reading: the override keeps
parsing, keeps resolving, and paints nothing — --in-content-page-background
did exactly that, and a theme's dialog body silently rendered white under its
dark palettes for months.
When fxcss can find this Firefox's omni.ja archives (it can, for every
packaged build), the audit reads the shipped chrome directly and separates
three cases a live probe cannot tell apart:
- set and read by Firefox — a working override, counted quietly;
- SET, NEVER READ — this Firefox still declares the name but no rule or script consumes it any more, so the override changes nothing;
- DEFINED ONLY — the shipped chrome neither declares nor reads the name,
with the closest consumed name suggested when there is one
(
--panel-background→--panel-background-color).
Reading the shipped sources also covers documents the live audit cannot open — dialogs, DevTools, in-content pages — and replaces the second, unthemed Firefox launch the probe needed.
A name you keep deliberately — for an ESR that still reads it, say — gets an inline pragma rather than a CI flag nobody finds later:
--in-content-page-background: var(--gnome-menu-background) !important; /* fxcss-keep: ESR 140 reads it */--strict-vars turns dead and stale overrides into a non-zero exit for CI;
fxcss-keep lines are exempt.
Unused and unreachable code
audit also reports housekeeping, in its own section, separate from breakage:
- Stylesheets nothing imports. Files under
chrome/unreachable by following@importfromuserChrome.css. Sheets in acustom/oroptional/folder are excluded — being opt-in is the point of those. - Custom properties used but never set, where an unthemed Firefox does not
provide them either. These are usually typos: the
var()silently falls back. - Custom properties set but read nowhere. Reported cautiously — setting
--arrowpanel-backgroundexists precisely so Firefox's own rules pick it up, so this section excludes every name an unthemed Firefox resolves.
The audit reads Firefox's shipped sources where available. Otherwise it uses a second, unthemed browser to distinguish theme-defined properties from those Firefox provides.
Pass --no-unused to skip the section.
Use --strict to fail on actionable selector findings and --strict-vars
for dead custom properties. Unreachable stylesheet reports remain advisory;
/* fxcss-keep */ marks deliberate property overrides.