In the CSS that we have today, they are still probably the least shitty solution in most cases.
attr() for things that aren't content isn't really supported and manually doing [data-gap="1"] {} [data-gap="2"] {} and so on sucks for various reasons. Attributes like [card-size="big"] look good, but unlike classes, they don't get autocompleted so you always have to remember the magic strings (ugh) and errors don't get caught by static analysis.
It's not just the class attribute that's harmful legacy garbage, but the core design of CSS. But we're stuck with it.
attr() for things that aren't content isn't really supported and manually doing [data-gap="1"] {} [data-gap="2"] {} and so on sucks for various reasons. Attributes like [card-size="big"] look good, but unlike classes, they don't get autocompleted so you always have to remember the magic strings (ugh) and errors don't get caught by static analysis.
It's not just the class attribute that's harmful legacy garbage, but the core design of CSS. But we're stuck with it.