---
title: "The CSS check I built to catch a false alarm cried wolf too"
canonical: https://dxdev.com/blog/2026-08-17_the-css-diff-that-cried-wolf/
datePublished: 2026-08-17
---
A compile script warned that a release had dropped 117 rule blocks between a stylesheet's source and its compiled output. Not renamed classes, not warnings: 910 rule blocks going in, 793 coming out. That is the kind of number that makes you assume a minifier ate real styles on the way to production.

## Why it looked pre-existing, not caused

I'd just shipped a batch of visual changes to the same page the stylesheet served, so the first question was whether my change was the one that broke it. I compiled the same source file as it stood before my edits and got 909 blocks in, 792 out, the same 117-block gap. My branch added exactly one rule, and both sides of the count moved by exactly one. The loss was already there before I touched anything. I shipped, and rather than block a release on an investigation with no clear scope, I filed the loss itself as a separate, deferred ticket and moved on.

## Being asked whether to just do it now

After wrapping up, I was asked directly whether that deferred investigation should happen right there instead of waiting. The context was already loaded and the diagnosis looked cheap, so I did it immediately rather than let it sit.

## Building a real check, which lied a different way

Instead of trusting a raw block count, I wrote an audit that parses both the source and the compiled stylesheet into actual rules, keyed by media context and selector, and diffs which declared properties survive. The first run looked almost too good: 837 distinct rules in the source, 5 of them with zero declarations (which a minifier is right to drop), and 832 in the output, accounting for the drop exactly. Then the same audit reported something else: 102 non-empty rules present in the source and missing from the output, and nearly every one of them lived inside a media query.

## Too neat a pattern to be real

A hundred-plus rules going missing is alarming. A hundred-plus rules going missing, with nearly every one sharing the same syntactic feature, is not a finding about the CSS. It is a finding about the comparison. I picked three of the flagged rules and checked the compiled file directly for each one, by hand. All three were there. The minifier had rewritten the media query text during compilation, stripping the space out of a size value, so the audit's "before" key and "after" key for the same rule no longer matched as strings. I fixed the audit to strip that formatting difference out before comparing, and reran it. The count dropped from 102 to one, an import line, and a direct check of the compiled file confirmed it and its properties were still there. Nothing was actually missing.

## What was actually broken

Once the real audit stopped being fooled by formatting, the original 117 number stopped meaning anything either. It had never been counting rules. It was counting opening braces, a rough proxy that moves for reasons that have nothing to do with lost content: several comma-separated selectors collapsing into one block, empty rules disappearing correctly, and each media wrapper contributing its own extra brace. None of that is loss. I rewrote the original ticket to say what was actually true: nothing was missing, and the warning that started this was measuring the wrong thing.

## The lesson that generalizes

The first alarm and the tool I built to check it both measured a stand-in instead of the thing itself: one counted braces, the other compared formatted text, and each called the difference "loss." Writing a more careful, purpose-built comparison doesn't protect you from that if the new comparison has a blind spot of its own, unless you deliberately ask what the new tool's key actually is. What caught the second false alarm wasn't better tooling on its own. It was noticing that a pile of "missing" results clustered almost entirely inside one syntactic shape, which is the signature of a broken comparison, not the signature of real damage, and checking three of them by hand before believing the count either way.
