Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BEM and "active" classes / Decoupling HTML and JS

I've started using BEM methodology to decouple my HTML and CSS ... and it works pretty well most of the time. Even if its only your personal opinion, i would still like to know how others deal with this:

Let's assume we need to build a simple navigation. The HTML looks similar to

<nav class="nav">
    <ul class="nav__list">
        <li class="nav__item">
            <a class="nav__link" href=""></a>
        </li>
        <li class="nav__item">
            <a class="nav__link" href=""></a>
        </li>
    </ul>
</nav>

I'm not sure if i need the ".nav_item" and ".nav_link" or if it's better pratice to use this instead

.nav__list > li { CODE }

But my real issue is how to deal with "active" classes (not just for navigations, but in general). Is it better to use specific "active" classes like ".nav_item--active", so you can just use a single class inside your CSS file or if using more general class names like ".is-active" works better? But then you need to specify your classes inside your CSS file like ".nav_item.is-active" or (which looks even worse to me) ".nav__list > .is-active".

Every method has its downsides. To me the second way looks wrong if using BEM, but if you are going for the first way you run into "troubles" with your JS, because you need to "hard-code" the specific class name into your JS

someElement.addClass(".nav__item--active");

That way your JS relies too much on your HTML structure (or doesn't this matter too much?), which might change... And this leads to the second question. I heard that it's good to decouple not only your HTML and CSS but also your HTML and JS. So you could for example use those ".js-" classes to add click events and all that kind of stuff to elements instead of using your "styling" classes to trigger those kind of events. So instead of using

<button class="btn btn--large"></button> // $(".btn--large") in jQuery

you would have

<button class="btn btn--large js-dostuff"></button> // $(".js-dostuff") in jQuery

I think this in combination with HTML5 data-attributes works for pretty much for anything, but i'm asking myself what happens to navigation or accordions or stuff like that. Is it better for maintainability to use those ".js-" classes as well (for every item)

<nav class="nav">
    <ul class="nav__list">
        <li class="nav__item js-open-subnav">
            <a class="nav__link" href=""></a>
            <ul class="nav__sub">
                <!-- ... -->
            </ul>
        </li>
    </ul>
</nav>

or should i use $(".nav__item")... in my JS in this case? But that way you don't really decouple your HTML and JS (at least as far i understood this topic). It's not just about navigations, but about all those kind of javascript interactions, like accordions, sliders and so on.

I'll hope you guys can share some best practices for those questions and help me out.

Thanks

like image 954
Daniel Avatar asked Nov 06 '13 23:11

Daniel


2 Answers

BEM methodology says you shouldn't use any global selectors such as tag selectors so use nav__item and nav__link.

The same story with active modifier. You shouldn't have any global entities (you can use mixes but that's a bit different thing). So the best way is to go with nav__item--active (or nav__item_state_active in classic BEM notation).

And BEM has sollution for JS, HTML (or templates) and actually any other block's technology.

The main idea is that block knows everything about itself: how it looks (css), how it works (js), what html it should produce (templates), its own tests, documentation, images, etc.

And as css technology of the nav block applies rules in declarative way (you define some selector and all the nodes which match this selector are styled with these rules) the same way you can describe js of the nav block.

Please take a look at http://xslc.org/jquery-bem/ which is jquery plugin which gives you possibility to work with blocks in BEM way easily.

And in case you use some build system you can put all these technologies in the same folder on filesystem:

blocks/
    nav/
        __list/
            nav__list.css
            nav__list.js
        __item/
            nav__item.css
        nav.css
        nav.js
        nav.test.js
        nav.png
        nav.md

Having such file structure you may go deeper to what BEM actualy is and try i-bem.js: http://bem.info/articles/bem-js-main-terms/

like image 185
tadatuta Avatar answered Oct 09 '22 10:10

tadatuta


Actually, js in terms of bem often considered as not such good idea. For instance, bem is great to localize and move relations in css to horizontal scale, but in terms of js it's hard to abstract logic in very complex applications.

In react.js you can use it for class naming, and that's it (we use it this way and it works fine!). I wrote a library for decoupling problem with naming.

like image 23
Bloomca Avatar answered Oct 09 '22 09:10

Bloomca