6

I'm trying to express a simple CSS3 selector in BEM:

CSS

.block__elem {
  /* ELEM RULES */
}

.block__subelem {
  /* SUBELEM RULES */
}

.block__elem:not(:last-child) .block__subelem {
  /* HOW CAN I EXPRESS THIS? */
}

HTML

<div class="block__elem">
  <div class="block__subelem">CONTENT</div>
  <div class="block__subelem2">OTHER CONTENT</div>
</div>
<div class="block__elem">
  <div class="block__subelem">CONTENT</div>
  <div class="block__subelem2">OTHER CONTENT</div>
</div>
<div class="block__elem">
  <div class="block__subelem">THIS SHOULD HAVE A SLIGHTLY DIFFERENT STYLE</div>
  <div class="block__subelem2">OTHER CONTENT</div>
</div>

How can I express the last selector in BEM terms?

The only way I can think of is to add a modifier

.block__subelem--not-last-child {

}

And then add the logic to the HTML from behind, but for me that's just wrong, it adds complexity server-side and it's error prone.

tzi
  • 8,719
  • 2
  • 25
  • 45
Minkiele
  • 1,260
  • 2
  • 19
  • 32

1 Answers1

-1

One purpose of BEM is predictability.

Theory

For example, in the following code made without BEM, you cannot expect different styles between the two elements with a title class.

<div class="article">
  <div class="title"></div>
  <ul class="comments">
    <li class="comment">
      <div class="title"></div>
    </li>
  </ul>
</div>
<style>
  .article > .title { }
  .comment > .title { }
</style>

With BEM, we explicit the block to reduce the selector weight and to give predictability. So we know by reading the HTML, that .article__title ans .comment_title are two independent classes.

<div class="article">
  <div class="article__title"></div>
  <ul class="article__comments">
    <li class="comment">
      <div class="comment__title"></div>
    </li>
  </ul>
</div>
<style>
  .article__title { }
  .comment__title { }
</style>

to sum up:

Two elements, with the same classes and the same in-block hierarchy, should have the same styles.

Practical case

In your example you should explicit the styles difference for the last .block__elem.

The natural solution is to use a modifier, like .block__elem--last:

<div class="block">
  <div class="block__elem">
    <div class="block__subelem">CONTENT</div>
    <div class="block__subelem2">OTHER CONTENT</div>
  </div>
  <div class="block__elem block__elem--last">
    <div class="block__subelem">THIS SHOULD HAVE A SLIGHTLY DIFFERENT STYLE</div>
    <div class="block__subelem2">OTHER CONTENT</div>
  </div>
</div>

But, in my opnion, it is often better to use a different element, like .block__last-elem:

<div class="block">
  <div class="block__elem">
    <div class="block__subelem">CONTENT</div>
    <div class="block__subelem2">OTHER CONTENT</div>
  </div>
  <div class="block__last-elem">
    <div class="block__subelem">THIS SHOULD HAVE A SLIGHTLY DIFFERENT STYLE</div>
    <div class="block__subelem2">OTHER CONTENT</div>
  </div>
</div>
<style>
  /* Common styles */
  .block__elem .block__sub-elem,
  .block__last-elem .block__sub-elem { }

  /* :not(:last-child) styles */
  .block__elem .block__sub-elem { }
</style>
tzi
  • 8,719
  • 2
  • 25
  • 45