<div class=article>
<div class=article-header>
<div class=article-quote>
<div class=quote-body>
... a bunch more HTML ...
</div>
</div>
</div>
</div>
Just one quibble over this specific example (not the broader concept, which is sound): it probably didn’t have to be div soup to begin with. Something like this may have been more reasonable:
<article>
<header>
<blockquote>
<p class=quote-body>
... a bunch more HTML ...
</p>
</blockquote>
</header>
</article>
This example also shows a weakness of custom tags compared with using the class attribute. An element can have only single name but may have several classes. And as classes are unordered set, one cannot in general emulate that with several elements as the nesting introduces an order absent in the class list.
I’d argue it’s a strength. You still have classes and custom attributes to reach for when you want an (effectively) unordered set, the difference is just that you define some boundary that’s exclusive. This reflects reality. Some helper classes work together by just slapping them together, but component-like classes, like a toggle and a hero image, don’t. If you do want to combine them, you need to think about how, potentially rearchitect, and implement it whether you’re using classes or tag names.
Good use case for @container, @scope and :has(), where you forgo class definitions and use --custom-properties on the parent scope/container which are inherited downwards based on the existence of a scoped DOM pattern/container query, or 'upwards' by using a :has(child-selector) on the parent.
Although be sure to avoid too many :has(:nth-child(n of complex selector)) in case of frequent DOM updates.
Honestly it depends what you're doing. A tag name is only correct when it unambiguously specifies the content. As in, a header is just a header - there's no "dual nature" that we have to support by allowing multiple tag names. This means the ontology you're representing has to be "linear" - you can have more specific and less specific tags, but never a "fork" where you could really choose either more-specific tag in order to emphasise a different "part" of the tag. Classes should always be for secondary properties, which are not the main "essence" of the content.
All I say above is a just a particular way of thinking about document markup, of course. If you don't agree with it, then tags are probably the wrong way to express what you're thinking of.
Hot take: div soup isnt bad because html isn't purely structural. It's a natural consequence of a poor design decision. Div soup is a consequence of the design decision to couple html elements to styling, state management, etc.
It made sense in 1996. It does not make sense now.