Notes · 19 August 2025
Stylesheets that age
The CSS in old projects ages worse than the rest of the codebase. A few habits that help.
The CSS in old projects ages worse than the rest of the codebase. The HTML usually still parses. The JavaScript usually still runs, with a few adjustments. The CSS, in my experience, is where you find the worst rot.
Some of this is unavoidable. CSS is more entangled with browser behaviour than the other layers, and browsers change. Some of it is self-inflicted, by writing stylesheets that depend on quirks that the spec has since clarified, or on workarounds that have been obsolete for years.
A few habits I have settled on, over the last few projects, that produce CSS that ages noticeably better.
Ship modern CSS without polyfills.
The instinct, when a feature is new, is to ship a polyfilled version. The polyfill almost always becomes the rot in two years. Ship the modern version, with a graceful fallback for old browsers (@supports), and let old browsers see the older version. The old browsers will fall away. The modern version will keep working.
Use semantic property names.
Logical properties (margin-inline-start, padding-block-end) age better than physical properties (margin-left, padding-bottom). The reason is not internationalisation, though it helps with that. The reason is that the meaning of the property is encoded in the property name, which makes the stylesheet more robust to refactoring.
Avoid frameworks that ship a lot of compiled CSS.
The frameworks that produce the longest-lived stylesheets are the ones that compile to small, self-contained CSS files. Tailwind, counter-intuitively, ages well, because the compiled output is plain CSS with semantic class names that map to declarations. Frameworks that ship a megabyte of utility classes that include their own reset, their own typography, and their own opinion about every property, age badly.
Comment the why, not the what.
/* full bleed because the design wants the image to span the column padding */ ages well. /* margin-left: -2rem */ does not. The first explains intent. The second restates the line below it.
Avoid magic numbers that are not tied to a token.
width: 47% is rot in a year. width: var(--column-width) survives a refactor. The pattern, even if you do not have a design system, is to put numbers that are doing work into custom properties at the top of the file. The properties are easy to read, easy to find, and easy to change.
Read the stylesheet six months later.
The single most useful exercise for writing CSS that ages well is to come back to a stylesheet you wrote six months ago and read it as if you had never seen it. The places you cannot follow the logic are the places that will rot first. Refactor those before they become a problem.
There is also a meta-point. Most front-end developers spend the first few years of their career trying to write CSS that is clever. The next few years are spent unlearning that, and writing CSS that is boring. Boring CSS ages well. Clever CSS does not.
For deeper reading on this: Manuel Matuzović’s writing on resilient CSS is the cleanest current treatment. Heydon Pickering’s Inclusive Components covers the same logic at the component level. MDN’s CSS reference is the canonical source for what features are actually stable in browsers, which is what determines whether your CSS ages or rots.