Search code examples
csslessbem

Does everything that has CSS attached in BEM need a class name?


As people are still advising to use BEM for larger projects I thought I might give it a shot. But I already run into a problem by setting up the header-element of the page.


This is how the page's header looks now:

<header class="header">
    <img class="header__logo" src="logo.png" alt="alt">

    <button class="header__button-toggle" type="button">Open menu</button>

    <nav class="header__nav" role="navigation">
        <ul>
            <li><a href="">Nav item A</a></li>
            <li><a href="">Nav item B</a></li>
            <li><a href="">Nav item C</a></li>
        </ul>
    </nav>
</header>

I understand how to define simple elements, like header__logo or header__button-toggle.


However I'm not sure what to do, when it comes to the nav-element. The HTML is not going to change, as this is a common and well approved pattern and will be the same in 5 years, I guess.

Now I need to apply styles not only to the nav-element but also to the ul, the li and the a-elements as well. How do I do this?

I would do it like this in Less:

.header {
    &__nav {
        property: value;

        ul { property: value; }
        li { property: value; }
        a { property: value; }
    }
}

But is this valid in BEM or is this what BEM wants to eliminate?


Must I end up with something like this instead?

.header {
    &__nav {
        property: value;

        &__list { property: value; }
        &__item { property: value; }
        &__anchor { property: value; }
    }
}

Which clutters the HTML extremely:

<nav class="header__nav" role="navigation">
    <ul class="header__nav__list">
        <li class="header__nav__item">
            <a class="header__nav__anchor" href="">Nav item A</a>
        </li>
        <li class="header__nav__item">
            <a class="header__nav__anchor" href="">Nav item B</a>
        </li>
        <li class="header__nav__item">
            <a class="header__nav__anchor" href="">Nav item C</a>
        </li>
    </ul>
</nav>

Maybe someine can help me understand, how this would be solved correctly in terms of BEM.


Solution

  • Yes, you should assign a class to each element you need to address in CSS (see: https://en.bem.info/methodology/html/#binding-blocks-to-a-dom-node). And you should not be afraid of extra bytes in your markup as gzip will compress it just fine.

    But you should avoid elements of the elements (please refer to: https://en.bem.info/methodology/faq/#can-i-create-elements-of-elements-block__elem1__elem2 for reasoning).

    So proper markup will be like this:

    <nav class="header__nav nav" role="navigation">
        <ul class="nav__list">
            <li class="nav__item">
                <a class="nav__anchor" href="">Nav item A</a>
            </li>
            <li class="nav__item">
                <a class="nav__anchor" href="">Nav item B</a>
            </li>
            <li class="nav__item">
                <a class="nav__anchor" href="">Nav item C</a>
            </li>
        </ul>
    </nav>
    

    You may also noticed that there are two different classes on nav element. That's called mix in BEM methodology: https://en.bem.info/methodology/css/#mixes