Press "Enter" to skip to content

Re: Affordances and Lean CSS

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:

can work for solo devs or small disciplined teams. You know your codebase. You can keep CSS lean through sheer will.

But teams of 5, 10, 20 with varying frontend experience? You need guardrails. You need something that makes the wrong thing hard.

December 15, 2025, 8:32 pm 0 boosts 1 favorites

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

  • Kerrick Long (code)

Leave a Reply

Your email address will not be published. Required fields are marked *

Your post must include a link to this post.

How does this work?
Write a response on your own website and include a link to this post. Then submit your response’s URL here. Your response may appear here after moderation. To update or remove it, edit or delete your original post and submit the same URL again. Learn more about Webmentions.