The anti-slop rules, one by one, and what each is actually for

9 min read

Eduardo Calvo

Eduardo CalvoWrote the skill and the detector this post measures with

A rule is only worth having if you can say what it prevents and what to do instead. Here are the ones that fire most often on generated code, with the reasoning rather than the slogan.

no-gradient-text

Gradient text needs background-clip: text plus a transparent fill, which means the text has no colour if the background fails to paint — and it fails on some Android WebViews and in forced-colors mode. It also has no contrast value you can measure, so nobody can tell you whether it passes. Instead: solid colour, and put the gradient on a surface behind it.

no-emoji-icons

Emoji render in a different family per platform, cannot inherit stroke weight, sit on a different baseline than the text next to them, and are read aloud by screen readers with names nobody chose (“rocket”, “sparkles”). Instead: a real icon set with one stroke width.

uniform-card-grid

Six identical cards in one row is the shape of a page that has not decided what matters. It is also the single most recognisable generated-UI tell. Instead: vary the size by importance, or use rows.

no-transition-all

transition: all animates properties you never intended — including height and top, which cannot be composited — and it makes every future change a performance surprise. Instead: name the properties.

hover-without-focus-visible

An interaction available to a mouse and not to a keyboard is a broken control, and it is the most common accessibility defect in generated code because hover is the state people demonstrate. Instead: pair every :hover with :focus-visible.

The two we changed after they caused a defect

perf/image-no-dimensions used to say “set the width and height attributes” and stop. Followed literally, that produces stretched images: the attributes are presentational hints, and the height one outranks aspect-ratio. It bit four of our own pages before it was measured rather than eyeballed. The fix text now names height: auto, and a second rule, layout/image-height-from-attribute, catches the shape.

css/duplicate-declaration was added after a wordmark shipped at 1.6:1 contrast: color was declared twice in one block, the pale value first and an older dark one last, and the last one wins. No rendered check can catch that class — the text sat over a photograph, where contrast is explicitly not measurable — so it had to become a source rule.

That is the honest pattern behind most of the list. A rule exists because something shipped wrong, and the rule is the shape of the mistake.