Stephen Margheim (fractaledmind) wrote Affordances: The Missing Layer in Frontend Architecture this month. This quick post is my reply to his great article.
I hear the objection already: “Isn’t this just… semantic CSS classes? We tried that.”
You’re right that we tried it. But “it didn’t work” deserves unpacking.
I was indeed objecting that in my mind. But I was not thinking, “it didn’t work.” I was thinking, “and it has kept working for decades. Obviously the utility-only workflow described is terrible; it’s why I refuse to choose Tailwind. How are affordances better than what’s worked for a decade?”
…and then I read further, and saw you are indeed recommending what’s worked for a decade, with CSS layers to solve the one pain point with that workflow, which they were invented to solve.
Remember that file input from the opening? Here’s how it looks with an affordance layer:
<label for="document-upload" class="ui-button"> Choose file </label> <input type="file" id="document-upload" class="sr-only" />That’s it. The gets the button affordance. The is visually hidden but remains accessible. The retains its native behavior—clicking it still triggers the file picker. No component gymnastics, no escape hatches, no fighting the framework.
I see now that I am not the target audience for the post, and I applaud Stephen for trying to bring folks back around to writing traditional CSS and using classes for certain … classes … of UI elements.
P.S. – I learned about the above post in this thread:
I don’t buy this as a reason to add a runtime dependency that pushes developers towards utility-first styling. If somebody extracted out just the tree-shaking part into a build-time dependency that didn’t try to introduce runtime styles, I’d probably like it. In the mean time, my IDE has code inspections that make it very clear what’s safe to delete. It includes an auto-fix, and can be configured to run on every commit. That configuration can be checked into source control and shared with the team.

Be First to Comment
Reposts