The Miller's Perfect Sieve: On the Grain Lost in a Pixel-Chasing Purge
The quest for the perfect Lighthouse score has become a familiar ritual. We strive for the ‘green,’ that coveted 90-something that validates our technical prowess. In this race, one commandment has become sacrosanct: purge the unused. With grim determination, we wield tools like PurgeCSS, sifting through our stylesheets, ejecting any selector deemed redundant. We celebrate the resulting sliver of a file, the kilobytes shaved, the milliseconds saved. The application, we are told, is now leaner, faster, more pure. But in our zeal to create the perfect sieve, are we inadvertently discarding the very grain that gives our work its flavour?
The argument against unused CSS seems unassailable. Why ship what the user doesn’t immediately need? It’s dead weight. Yet this logic rests on a dangerously narrow definition of ‘use.’ It assumes the user’s journey is a straight, predictable line, and that the only styles of value are those required for the initial paint. It treats the browser not as a dynamic environment for interaction, but as a static canvas. In the miller’s workshop, obsessed with purity, we risk throwing out the seeds needed for next season’s crop.
Consider the simple, delightful micro-interaction. A hover effect on a button that wasn’t ‘critical.’ A subtle animation that clarifies a state change. A modal dialog that slides in gracefully. These are the details that transform a functional interface into a crafted experience. When we purge aggressively, we often sever the connection between the initial state and the interactive one. The styles for the ‘active’ or ‘hover’ state of a component might be deemed ‘unused’ on page load and ruthlessly culled. The user clicks a button, and instead of a satisfying response, they get… nothing. The interaction feels brittle, hollow. We saved a few bytes and sacrificed the feedback that makes an interface feel alive.
This purging mania also creates a brittle development cycle. Every new feature, every A/B test, every content update becomes a potential performance regression. The act of adding a simple class to a button now requires a rebuild and a re-purge of the entire stylesheet. The system becomes fragile, hostile to iteration. The very agility that modern tooling promises is undermined by the constant threat of breaking styles for parts of the application that are just one click away. We trade long-term resilience for a temporary, often negligible, performance gain.
This is not an argument for bloat. It is a plea for context. The wisdom lies not in purging everything, but in knowing what to keep. Perhaps the solution isn't a more aggressive sieve, but a smarter mill. Component-scoped styles, strategic chunking, and a healthy respect for the full lifecycle of an interaction are more sustainable paths. Speed is not merely the absence of bytes; it is the presence of a fluid, responsive, and predictable experience. Before we purge in the name of performance, we must ask what kind of experience we are building, and what we are willing to lose for a few points on a scorecard that will never measure the feeling of a seamless hover state.
Notes & further reading
A few pages I came back to while writing this:
- a practical rundown
- The Blacksmith's Cold Anvil: On the Brittle Edge of an Over-Forged Experience
- a local resource
- The Cartographer's Lost Step: On the Unexpected Cost of a Deferred Interaction
- a nearby resource
- The Cartographer's Uncharted Blank: On the Hidden Cost of a Missing CLS Target
- a helpful reference
- one area's overview
- a regional guide
- a place-by-place guide
- a useful directory
- a nearby resource
- a regional guide