8

I've been working through this article to organize my front-end code. It references articles on BEM / SMACSS, which in turn reference other articles.

I'm really trying to understand what the best practices are ... I have a few days to lay down this "standard", and then have to burn through a high-priority / high-visibility / limited timeline project. As such, I'd like to ensure I'm starting with a foundation that will scale as my app does.

Given a component named segment ... I'm creating pages that will have ~10 segments per page. Each segment will share the same base class. However, certain segments will have modifiers on them (different background colors). Further, elements within each block (in the BEM approach) will have modifiers as well. To demonstrate, here is a simple implementation (with only a single element arrow, while my full site will have 4-5 elements in each segment):

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow--orange {
    @extend .segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--white {
    @extend .segment__arrow;
    background-image: url('/images/arrow_white.png');
}

So this is the single-class approach:

<div class="segment__arrow--white"> ... </div>

Alternatively, I could go with the multi-class approach:

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow--orange {
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--white {
    background-image: url('/images/arrow_white.png');
}

Where my markup would be:

<div class="segment__arrow segment__arrow--white"> ... </div>

Third, I could do:

.segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}
.segment__arrow.orange {
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow.white {
    background-image: url('/images/arrow_white.png');
}

And then my class def would be

<div class="segment__arrow orange"> ... </div>

Perhaps even namespacing orange with something like sa_orange to avoid loose selectors.

The end result I'm looking for is less code / easier to maintain (which probably rules out the single class approach (option 1), as described in this great article on scalable architecture. The multi-class approach (option 2) results in a lot of verbosity (especially in my HTML), but is extremely explicit. The third uses a multi-class approach, but doesn't use namespaced modifiers (like .segment__arrow), so is slightly less verbose (but also less explicit & higher potential for collisions).

Does anybody with real world experience with this stuff have any feedback on the best way to approach this?

3
  • De-coupling the modifiers from the elements goes against these principles, right? .orange has no meaning as a modifier alone. I don't see a big problem in using .segment__arrow--orange along with your multiclass approach. Of course in bigger projects your HTML could get a little bit out of control (lots of classes). Commented Dec 29, 2013 at 20:59
  • Away for holiday. Thanks for the response. Yeah, that's why I have been noodling on the third option. You're correct, it does go against these principles, but as a project scales, I'm imagining a class="segment__arrow segment__arrow--orange segment__arrow--is-visible segment__arrow--something-else" ... and that just starts to get a bit code smelly for me ... Commented Jan 2, 2014 at 14:14
  • True. One shouldn't drive this whole BEM bus too far. Not everything needs to be BEMified. Commented Jan 2, 2014 at 14:39

2 Answers 2

8

For a long time I have been using and recommending the explicit multi-class approach (the second example) as it is the most universal, maintainable, and coherent. Here I will try to support this claim.

Single-class

This approach has a big problem when there are two or more categories of modifiers. For example a .button with modifiers small, large, huge for size and primary, success, info, and warning for "colour." On top of the usual 7 (= 3 + 4) classes one has to create all 12 combinations too:

.button--small--primary
.button--small--success
.button--small--info
…

So far a bit inconvenient but not a disaster.

Another annoyance - a bigger one - is that the correct order "size first, colour second" must be used and therefore remembered (and well documented).

The worst is when JavaScript is involved. Want to change the "colour" of this button but keep the current size? Parse the class attribute! Want to just remove the success modifier? Parse the class attribute!

Count that e.g. Bootstrap has 7 "colours", 4 sizes, and active/disabled states; for which 119 (= 13 + [7*4 + 7*2 + 4*2] + 7*4*2) classes have to be declared in order to maintain single-class approach! That is the big problem.

Explicit multi-class would require just 13 classes (one for each modifier). The order would be arbitrary. Lastly, adding, removing, and changing one while preserving others would in jQuery look like:

$('#login-button').removeClass('button--primary').addClass('button--success');

Shortcut multi-class

Firstly, as you mentioned, there is a potential for collisions - a bad thing by itself.

Secondly, what it also means, is that the .segment__arrow.orange has a higher specificity and cannot be overwritten with a single class selector. This is often in issue when an element is e.g. not only a large button but also e.g. a login button. Its code would look like:

<a href="#" class="button large primary login__button">Log in</a>

One might want to have a bigger left and right padding on the login button but preserve the height of large. This would result in more and more specific selectors which would bring us to the specificity hell - a place OOCSS should save us from.

It is evident this would not happen in the explicit multi-class approach.

Explicit multi-class

The only problem (as far as I am aware of) of this is that there are a few sometimes quite long classes in the markup. I do admit this.

Let me note that this is only a matter of taste of the developer as it has a negligible (to no at all) effect to the performance. The standard compression will take care of this.

That being said, using a good IDE will help to write these (yes, I know, it still will look a bit ridiculous).

On one hand, I would say, seeing such long classes forces one to think more about the structure; e.g. whether it would not be better to introduce a new (reusable) component instead of nesting it into something else.

0

I am debating with my teammates about this Single/ Multi Class issues right now

here are some of my personally views based on best practise

Best Practise

  • html declares elements
  • CSS controls render

Single Class is always following the Best Practise

with extra maintaining benefits, with good names it can achieve

  • style change requires no html update*(see demo)

  • locking style in html(you will have the right style or nothing)

Demo

@mixin segment__arrow {
    position: absolute;
    bottom: -24px;
    left: 50%;
    margin-left: -11px;
    background-position: center no-repeat;
    height: 21px;
    width: 21px;
    z-index: 2;
}

.segment__arrow--type1 {
    @include segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
.segment__arrow--type2 {
    @include segment__arrow;
    background-image: url('/images/arrow_white.png');
}

@mixin include is better than @extend

  1. have control of code order in final css
  2. smaller size in gzip version

and same as @extend, it is can be reused and can replace multi class in HTML

with @mixin, you will gain extra flexibility

@mixin segment__arrow--type1 {
    @include segment__arrow;
    background-image: url('/images/arrow_orange.png');
}
@mixin segment__arrow--type2 {
    @include segment__arrow;
    background-image: url('/images/arrow_white.png');
}
.segment__margic-arrow {
    @include screen(mobile) {
       @include segment__arrow--type1
    }
    @include screen(desktop) {
       @include segment__arrow--type2
    }
}

For javascript use

state rules of smacss

Drawback of Single Class

one and only:

bigger CSS files size, BUT you can always easily optimise CSS based on website sections or components in the page

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.