1

I am trying to learn BEM and having difficulty appreciating it's benefits. As an example, I went to Tailwind's Utility-First page to grab this code:

<div class="chat-notification">
  <div class="chat-notification__logo-wrapper">
    <img class="chat-notification__logo" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div class="chat-notification__content">
    <h4 class="chat-notification__title">ChitChat</h4>
    <p class="chat-notification__message">You have a new message!</p>
  </div>
</div>

  .chat-notification {
    display: flex;
    max-width: 24rem;
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background-color: #fff;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  }
  .chat-notification__logo-wrapper {
    flex-shrink: 0;
  }
  .chat-notification__logo {
    height: 3rem;
    width: 3rem;
  }
  .chat-notification__content {
    margin-left: 1.5rem;
    padding-top: 0.25rem;
  }
  .chat-notification__title {
    color: #1a202c;
    font-size: 1.25rem;
    line-height: 1.25;
  }
  .chat-notification__message {
    color: #718096;
    font-size: 1rem;
    line-height: 1.5;
  }

When I look at it, I can't help but think it should be simplified to just

<div class="chat-notification">
  <img src="logo.jpg" alt="ChitChat Logo">
  <h4>ChitChat</h4>
  <p>You have a new message!</p>
</div>

.chat-notification {
  position:relative;
    max-width: 24rem;
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background-color: #fff;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  box-sizing:border-box;
  padding-left: 3.5rem;
}
.chat-notification img {
  position:absolute;
  top:0;
  left:0;
  clip: rect(0,200,400,0);
    width: 3rem;
}
.chat-notification h4 {
    color: #1a202c;
    font-size: 1.25rem;
    line-height: 1.25;
}
.chat-notification p {
    color: #718096;
    font-size: 1rem;
    line-height: 1.5;
}

I basically simplified the HTML and got rid of unnecessary wrappers, divitis, classitis. My question is why are class descriptors like __logo-wrapper and __title useful when tags like img, h4, p are already quite distinctive and semantic?

John
  • 32,403
  • 80
  • 251
  • 422

3 Answers3

4
  1. Cascades don't scale. A selector .chat-notification img or .chat-notification h4 implies that your block chat-notification doesn't includes a sub-block which could use an <img> or a <h4> element.
  2. Using elements in selector makes the code inflexible. You might want to display a <svg>, a <canvas>, a <video> instead of an <img> but with your current CSS code it'll be required to change the CSS code before. Your SEO consultant will ask you to replace the <h4> with a <h2> and you'll have to change your CSS selectors.

[EDIT] Related to classitis: BEM, Cascading styles and Classitis?

Paleo
  • 21,831
  • 4
  • 65
  • 76
0

Well done, but now if you try to put modified code to some page with the same idiom it won't work. This means that cascades doesn't work as you want to. CSS Modules can be an option to solve this problem but it uses classes too.

Also there are no real life reasons to drop classes in html elements in the most cases. Browsers loves classes and styles binded to them. Single level classes works much faster than cascades. Transferred bytes are approximately equal because of zopfli/brotli. Dropping classes just make source code reading harder.

But it's just about classes.

I basically simplified the HTML and got rid of unnecessary wrappers, divitis

Simplifying html markdown is a good thing usually. logo-wrapper and content elements are just redundant and dropping them not contradict to BEM. E.g.:

<div class="chat-notification">
  <img class="chat-notification__logo" src="logo.jpg" alt="ChitChat Logo">
  <h4 class="chat-notification__title">ChitChat</h4>
  <p class="chat-notification__message">You have a new message!</p>
</div>

why are class descriptors like __logo-wrapper and __title useful when tags like img, h4, p are already quite distinctive and semantic?

Actually, the example is not eloquent because of simplicity. Here we have just three fields and a container. When you'll have few images or few different "messages" (e.g. pros and cons fields) you'll need to mark img and p tags. Also img is not semantic thing, it's an entity of HTML world, but not yours. It's not just an abstract image, it's a logo, so better mark it semantically.

Better to think of HTML as a low-level generated thing that helps translate our applications to browsers. That's why libraries like BEMHTML and bem-react exists.

E.g.

({
    block: 'chat-notification',
    content: [
        { elem: 'logo', image: 'logo.jpg', text: 'ChitChat Logo' },
        { elem: 'title', content: 'ChitChat' },
        { elem: 'message', content: 'You have a new message!' }
    ],
})

Example with templates

Alex Yaroshevich
  • 710
  • 8
  • 19
0

The non-BEM CSS is tightly coupled to the HTML, I.e. changes to the HTML will likely lead to changes to the CSS. I’d argue this goes against SOLID coding principles, breaking the open-closed and possibly the single responsibility principle.

It’d be better if the CSS wasn’t so tightly coupled to the HTML.

BEM helps with this by allowing you to create an abstract structure of CSS classes that aren’t strictly tied to the HTML elements and can be applied more flexibly.

It comes at a cost that you and your team need to remember what that abstraction is but I feel it’s minimal because BEM is a fairly simple model.

You can also run into issues in large codebases where naming collisions can occur, but there are tools to help you get around this, such as CSS Modules.

Personally I love BEM and use it whenever I can.

HNipps
  • 456
  • 3
  • 15