Bootstrap is quite the opposite of what I'd consider good CSS architecture (although it's obviously a great project). Way too much reliance on DOM structure.
On a larger scale (overall layout of a page) CSS reliance on DOM structure is a bad thing. But on a small scale (layout of a component) the cleanest markup is usually going to require coordination between the CSS and the DOM structure (and JS if the component has custom behaviors.)
This is true for basic html too. You could create a bullet list by adding a div with a class for the container and arbitrarily located divs with classes indicating that they're list items related to the container, and then use complicated CSS to pull it all together into a visual representation of a bullet list. Or, you could use a ul element for the container with direct child li elements for the items. Your visual style relies on the DOM structure, but overall it's a cleaner solution.
Why would you create a list with <div> elements? I understand your point; DOM structure has styling defaults and you have to play with it - 100% decoupling it's not possible. Still, trying to achieve decoupling between structure and styles doesn't mean that you should create bad mark-up.
In your scenario, I'd use a list element (<ul> or <ol>, according to the nature of the data) with a class (e.g. .my-list) and list item elements also with a class if needed (<li> with e.g. .my-list__item). No complications here. If somewhere along the way someone wanted to to a navigation area with exactly the same styles but with a different mark-up (anchors inside a <nav>), you could reuse or extend those classes to a <nav> element for the container and <a> elements for items. That's another "level" of DOM independence.
That's exactly how Bootstrap's classes for lists work. And they are tied to the DOM structure, though not necessarily to particular elements: .my-list has to go on a container element, and .my-list__item has to go onto children of that element.
The point I was trying to make was that at a component level, your CSS classes are usually going to depend on a particular hierarchy in the DOM elements that the classes are applied to, or they won't work correctly. How much of a dependency you have is a tradeoff; you can design your framework to minimize the dependency, but you're likely to create a more complicated framework in exchange.
> That's exactly how Bootstrap's classes for lists work. And they are tied to the DOM structure, though not necessarily to particular elements: .my-list has to go on a container element, and .my-list__item has to go onto children of that element.
Not quite exactly. My solution doesn't require list items to be child elements of the list. Bootstrap's "list item" needs (by definition/rule) to be a "direct" descendant - a child element of a given type (a selector with "> li") of the list. They have classes for lists, and then style the list items via element and "descendancy" (i.e. .my-list > li).
If somewhere along the way you decide/are asked to change the mark-up in order to have an element for grouping list items (so, you'd have elements between the list and list items ), Bootstrap's way of creating rules wouldn't work anymore - list items wouldn't be child elements of the list, despite you wanting to keep the styling in them. Independently of how you solved this in the mark-up, if your rule was like Bootstrap's .my-list > li, then it wouldn't work anymore because list-items wouldn't be "direct" descendants of .my-list.
This might seem minor or unusual, but I assure it's not - this is the kind of changes in structure that happen very frequently and make DOM-tied CSS fail. And bear in mind the Tetris effect on this: your less-than-experienced team member might solve this with yet another rule, but a even more specific one (.my-list > .group > li) which will yield harder to maintain CSS (this rule is very specific; it would need even more specific rules to be overridden when necessary). If your development rule was "no DOM tying; just use classes), the problem of escalating specificity would've also been avoided.
> The point I was trying to make was that at a component level, your CSS classes are usually going to depend on a particular hierarchy in the DOM elements that the classes are applied to, or they won't work correctly. How much of a dependency you have is a tradeoff; you can design your framework to minimize the dependency, but you're likely to create a more complicated framework in exchange.
I understand your point, but I don't agree with the notion that "but you're likely to create a more complicated framework in exchange" by minimizing the dependency on the DOM. You're likely, definitely, to create a more verbose CSS framework, with a way bigger amount of classes. But I don't think this is the same as complicated; it's more verbose, it may require you to write more code[1], but I think it's very predictable and easier to follow by team members with different expertise levels.
P.S. Also, bear in mind that BEM-like solutions also have hierarchy. Elements which belong to blocks. They just don't depend on a specific hierarchy on the DOM; DOM hierarchy is independent of styling hierarchy.
[1] I'd argue it will make you write more code in the beginning. Traditional DOM-tied styling will eventually catch-up and the code you have to write to overwrite "over-specific" selectors and similar issues will grow bigger.