suitcss / suit

Style tools for UI components
http://suitcss.github.io/
3.8k stars 229 forks source link

Best method for handling same nested block with different modifier? #144

Closed rmunch closed 5 years ago

rmunch commented 7 years ago

I'm running into an issue where I have a very generic block with a handful of modifiers where, when nesting this particular block inside itself, the top-level modifier styles leak into the child block.

# style.css
.ContentList--small .ContentList-item {
    margin-bottom: 10px;
}

.ContentList--large .ContentList-item {
    margin-bottom: 30px;
}

#content-list.html
<div class="ContentList ContentList--large">
    <div class="ContentList-item">Content 1</div>
    <div class="ContentList-item">Content 2</div>
    <div class="ContentList-item">
        <div class="ContentList ContentList--small">
             <div class="ContentList-item">Small content 1</div>
             <div class="ContentList-item">Small content 2</div>
        </div>
    </div>
</div>

Demo: https://jsfiddle.net/v7z5v4kx/

The problem is that the large margin is being applied to the ContentList-item elements of the inner ContentList when I want it to use the small margin.

At first I thought I'd use the direct child selector to limit the styling to the first level (ex. ContentList--large > .ContentItem), but I don't have that much control over the markup in this particular case. This method also seems to reintroduce a CSS specificity battle that (I think) BEM tries to avoid.

I wonder how I might avoid this situation? Should the ContentList-item elements be their own standalone block? Or maybe I should use an element modifier instead (ContentList-item--small)?

Thanks!

giuseppeg commented 7 years ago

This method also seems to reintroduce a CSS specificity battle that (I think) BEM tries to avoid.

BEM and SUIT are pretty much the same thing just with different naming convention. SUIT is also backed by tools and a better (imho) formalized methodology.

I wonder how I might avoid this situation? Should the ContentList-item elements be their own standalone block? Or maybe I should use an element modifier instead (ContentList-item--small)?

I think that the former might work better. Not sure if you are familiar with React but when in doubt I ask to myself: "how would I do that with React components". In this case the answer is similar to your solution I guess:

<ContentList>
   <ContentListItem small />
</ContentList>
oleersoy commented 7 years ago

Or just use a margin utility to tweak the css as needed. Margin utility examples here - see test 4

frekyll commented 7 years ago

@rmunch Since you have limited flexibility, I would resort to making the items their own component. In this example I used the shared namespace, but that doesn't matter. What matters is that the styles don't leak in this example.

<div class="ContentList">
    <div class="ContentListItem ContentListItem--large">Content 1</div>
    <div class="ContentListItem ContentListItem--large">Content 2</div>
    <div class="ContentListItem ContentListItem--large">
        <div class="ContentList">
             <div class="ContentListItem">Small content 1</div>
             <div class="ContentListItem">Small content 2</div>
        </div>
    </div>
</div>
.ContentListItem {
    margin-bottom: 10px;
}

.ContentListItem--large {
    margin-bottom: 30px;
}

I also created a third-party SUIT CSS utilities package for quickly adding space around objects.