Skip to content

Instantly share code, notes, and snippets.

@csswizardry
Created October 2, 2012 20:09
Show Gist options
  • Save csswizardry/3822990 to your computer and use it in GitHub Desktop.
Save csswizardry/3822990 to your computer and use it in GitHub Desktop.
Thoughts on BEM for inuit.css

Bringing BEM to inuit.css

BEM is a methodology for naming and classifying CSS selectors in a way to make them a lot more strict, transparent and informative.

The naming convention follows this pattern:

.block{}
.block__element{}
.block--modifier{}
  • .block represents the higher level of an abstraction or component.
  • .block__element represents a descendent of .block that helps form .block as a whole.
  • .block--modifier represents a different state or version of .block.

If you are familiar with OOCSS then you will no doubt be familiar with the media object. In BEM form, the media object would now read:

.media{}
.media__img{}
.media__img--rev{}
.media__body{}

From the way this CSS is written we can already glean that .media__img and .media__body must live inside .media and that .media__img--rev is a slight variation on .media__img. All that information gathered from CSS selectors alone!

This is a powerful feature. This is what inuit.css is about.

BEM would also enforce stricter use of classes. A lot of times (and I have seen it) developers will use a class in their HTML because the styling applied to that class simply happens to work in a certain context. It shouldn’t be used in that context, but by pure coincidence it just works. This means that—if the styles on the class they used ever change—it may have negative ramifications in their implementation that they might not be able to explain or understand. By namespacing things (e.g. .media__img rather than .img) then developers are a lot less likely to use classes in the wrong place. BEM will enforce much stricter limitations.

Another benefit I can see is the combatting of the following situation. If we take the media object again:

<div class=media>
    <img src=logo.png alt="Foo Corp logo" class=img-rev>
    <div class=body>
        <h3 class=alpha>Welcome to Foo Corp</h3>
        <p class=lede>Foo Corp is the best, seriously!</p>
    </div>
</div>

How are the classes .media and .alpha related to each other? Are they? What about .body and .lede or .img-rev and .media? From that HTML (unless we’re very familiar with the media object) we have no idea what makes up that component and what else is optional. If we were to rework it with BEM:

<div class=media>
    <img src=logo.png alt="Foo Corp logo" class=media__img--rev>
    <div class=media__body>
        <h3 class=alpha>Welcome to Foo Corp</h3>
        <p class=lede>Foo Corp is the best, seriously!</p>
    </div>
</div>

We can now instantly see that .media is the block, .media__img--rev is an element of .media that has a modifier applied and .media__body is an unmodified element of .media. All through the names of their classes. That is incredibly useful.

BEM may look a little funny, and it might require more typing (most text editors have autocomplete, and gzip will negate any differences in filesize) but it is so powerful, and inuit.css is all about power…

inuit.css is a powerful framework. It’s not a framework that’ll give you some nice glossy buttons; it’s a framework that will allow you to scale a 1,000+ page website, it’s an object oriented framework designed for use on big projects with big teams. One of the things I spoke about most recently was handling CSS in larger teams and I believe BEM is a great step in that direction.

BEM allows us to namespace our styles for stricter and appropriate implementations, it allows us to work out HTML’s relationship to itself (or if there is no relationship at all), it allows us to see what role a piece of HTML plays in a wider picture. inuit.css was designed to be scalable and used on larger projects with larger teams and I believe, although unsightly at first, BEM will massively help that.

I think the odd looking syntax (and my open hatred of underscores) is a fair price to pay for the value BEM notation would give us… Thoughts?

Comment on this post on GitHub.

@emzo
Copy link

emzo commented Oct 2, 2012

I think this is an excellent idea. I've been following OOCSS and SMACSS for a while, but hadn't really taken much notice of BEM. I've obviously been missing out. As you've shown, BEMs strict naming convention really does add a lot of contextual meaning to classes.

@PavelDemyanenko
Copy link

Cool, BEM makes support large projects much more easier. You may take a look at https://github.com/lvivski/boss and https://github.com/bem/bem-tools ;). And in BEM modifiers looks like .b-block__element_mod, not .b-block__element--mod.

@i-like-robots
Copy link

As an aside, Nicolas Gallagher also wrote on a similar topic and shares some of your conclusions. It's also worth a read. http://nicolasgallagher.com/about-html-semantics-front-end-architecture/

I think it may also be worthwhile discussing when and when not it is a appropriate to use BEM style naming conventions. We found them useful for structural stuff - like the media object as you mention, or creating the skeletons of components such as tabs - but it quickly became a mess when developers (myself included) attempted to the follow the patterns to a granular level.

We do still use the pattern but only as mentioned above, for abstracts and creating skeletons. Combined with (my favoured) Zen-Coding comments you get very expressive, documented source code.

@larrybotha
Copy link

I'm not entirely keen on the BEM underscore style of namespacing, but have found the namespacing itself invaluable.

I've modified my media block so as to not assume that the first child of the block is an img - digging through Podio's source and seeing how much and where they use the media object opened my eyes to just how crazy the media block is, and how naming the first child as an image of some sort doesn't do it justice.

I've opted for the following naming scheme for my media blocks:

.mblock {}
    .mblock-alpha {}
    .mblock-beta {}

where .mblock-alpha represents the traditional .img element. Makes me feel at ease when not using an image (:P), as well shows to who the element belongs, as mentioned.

I generally reserve -alpha -beta etc. namespacing for my modifier classes (as in your post on using rems to maintain vertical rhythm), so I may revisit this particular block at a later stage.

I'm even developing a styleguide with a Sass structure abstracting core concepts in my files beyond that of those outlined in BEM. My Sass is split into variables, utilities, and partials (where BEMs will actually fall under).

Variables are only to be declared under my var folder, css mixins and functions are only to be declared under my utl folder, and all blocks will then go under my par folder where they will eventually be abstracted into block, modifier, and media query sections.

Many of the modifiers I intend on adding to blocks will be namespaced according to the variables they reference. It's made modifying blocks with colours completely trivial, and that's just the beginning!

Great to see BEM and OOCSS gaining exposure!

@millermedeiros
Copy link

@necolas wrote about it on this gist: https://gist.github.com/1309546 - I'm also doing something similar on a few projects but it can get really verbose if we have too many nested components. I think we should try to keep it "shallow" whenever possible. The main idea is to avoid name conflicts and descendent selectors (avoid specificity problems) but it can also reduce code reuse if abused.

@caycefischer
Copy link

@larrybotha That's a great system you described!

I'm not keen on the underscore syntax either, for what it's worth, but I'm willing to give it a shot for inuit.css. I like the approach, at the very least.

@necolas
Copy link

necolas commented Oct 4, 2012

This looks like the structural naming conventions that I wrote about, not those that BEM specifically uses.

@kikito
Copy link

kikito commented Oct 18, 2012

I've already commented this on twitter, but allow me to develop my argument a bit further.

I don't like BEM. Generally speaking, I think it's cruft: hungarian notation for CSS.

Its main objective seems to be what you mentioned: encouraging the usage of certain html classes only on certain occasions. I think that is a valid objective. I don't like BEM's means to achieving it - and I don't think they will be particularly effective either. My reasons:

1- There is one obvious drawback, that you yourself mentioned: verbosity. However, I don't put as little importance as you do on that regard. In my opinion, good code is succint, not because it saves typing, but because it saves thinking. Brief text is easier to grasp than long text; our brains deal with those better. Shorter text is more pleasant to work with than a long text (for the length parameters we are discussing here).
2- There are other ways to make those "implicit rules of hierarchy" more explicit. I'm sure you know these better than me: indentation of "subrules", spacing, and documentation, for example.
3- You mention that "developers are a lot less likely to use classes in the wrong place". I'm sorry but I don't agree with that. Let's analyze the options here. I see 3 possible situations. A developer who misuses a css class has either:
a) Not read the css framework's documentation - be it source code, manual, or comments or indentation on the CSS files.
b) The documentation was non-existant.
c) The dev did find the documentation, but decided to misuse the class anyway.

Now, in a) BEM doesn't really change anything. A dev who uses the img class without reading its context might as well use media__img. If he's not read the css framework docs, it's more than likely that he doesn't know about BEM rules anyway. It will just be more letters to type. In the case of b) - the solution is obviously writing better docs. c) Is similar to a) actually - if the dev does not want to follow the css directives, then he'll not follow BEM anyway.

4- Regarding the "media vs alpha" situation: I don't think that the HTML is the right place to enforce the "separatedness between classes". I think that's the CSS framework's documentation's job. That is the authority one should refer when trying to understand how the classes interact with each other. We don't need two authorities for that. "Don't Repeat Yourself" echoes profoundly in my head when I read the last paragraphs in the OP.

I hope I don't sound angered - I'm trying to give my reasons logically. I do enjoy your css wizaldry posts quite a lot, and I have even used Inuit in a small website (the week before you announced its complete rewrite :/). I would like to try it again in the future, but I will not if it adopts BEM.

@matyus
Copy link

matyus commented Oct 18, 2012

I have devised a similar technique for things like the media object abstraction, with one small exception: I make a point of not using one-word classnames anywhere in my codebase. It's really tough to gather context from a single word as generic as '.media', same goes with things like '.nav'. I've found that it's crucial to pair it with some sort of context, nav_list, nav_sublist, etc.

So, .media doesn't fly.

.media {}
.media-image{}
.media-body{}

Instead, I've been using the suffix _module for setups like this. It helps denote that the parent (media_module) will have children somewhere that relate directly to this abstract system and aren't a single instance:

.media_module {}
.media_image {}
.media_body {}

I haven't completely adopted the BEM syntax, but I agree that the concepts behind BEM (that drive the syntax) are definitely worthwhile.

@varya
Copy link

varya commented Oct 18, 2012

@necolas, Just to clarify, BEM does not require any specific convention. The one described in the Smashing Magazine article was just an example of BEM-based naming convention what a particular team uses. Another team is free to use different naming. But if they have blocks, elements and modifiers, this is also BEM.

@YemSalat
Copy link

You guys suck..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment