0
\$\begingroup\$

I've been messing around with SASS and BEM for the last few months. I recently starting 'thinking' in modular in terms of building out my applications (for re-usability and simplicity).

I am coding my modules at the minute using the template fellow. I have tried to build this as simple as possible so that if I ever come back to my code, I will be able to figure it out as quickly as possible without moving back and forth to try and identify which element does what.

HTML

<div class="moduleType">
    <div class="moduleType__moduleName">
        <div class="moduleType__moduleName__block">
            <div class="moduleType__moduleName__block__element moduleType__moduleName__block__element--modifier1">
                <p class="moduleType__moduleName__block__element__p moduleType__moduleName__block__element__p--modifier1"></p>
            </div>
            <div class="moduleType__moduleName__block__element moduleType__moduleName__block__element--modifier2">
                <p class="moduleType__moduleName__block__element__p moduleType__moduleName__block__element__p--modifier2"></p>
            </div>
        </div>
    </div>
</div>

SCSS

.moduleType {
  &__moduleName {
    &__block {
      &__element {
        &--modifier1 {
        }
        &--modifier2 {
        }
        &__p {
          &--modifier1 {
          }
          &--modifier2 {
          }
        }
      }
    }
  }
}

Here is my module. I would love to know if anyone has any pointers or advice on how I could further simplify/optimise my coding structure.

HTML

  <!-- Module Start -->

    <!-- cardItem Start -->
    <div class="container-fluid socialFeed__cardItem">
      <!-- cardItem Hero Start -->
      <div class="row">
        <div class="col-xs-24">
          <div class="socialFeed__cardItem__heroImg__cont">
            <img src="" class="img">
          </div>
        </div>
      </div>
      <!-- cardItem Hero End -->
      <!-- cardItem Info Start -->
      <div class="row">
        <div class="col-xs-24">
          <div class="socialFeed__cardItem__info">
            <div class="row">
              <div class="col-xs-7">
                <div class="socialFeed__cardItem__info__playerImg__cont">
                  <img class="img" src="../assets/img/IMG_0894.jpg">
                </div>
              </div>
              <div class="col-xs-17">
                <div class="socialFeed__cardItem__info__playerText__cont">
                  <h5 class="name">Person Name</h5>
                  <p class="text">Consectetuer adipiscing elit. Aenean commo doligula eget dolor...</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- cardItem Info End -->
    </div>
    <!-- cardItem End -->

  <!-- Module End -->

SCSS

//---- widgets__socialFeed START

.socialFeed__cardItem {
  width: 205px;
  height: auto;

  &__heroImg__cont {
    border-top: 1px solid #000000;
    border-left: 1px solid #000000;
    border-right: 1px solid #000000;
    border-bottom: 1px solid #000000;
    background: gray;
    height: 165px;
    width: 100%;

    .img {}
  }

  &__info {
    border-left: 1px solid #000000;
    border-right: 1px solid #000000;
    border-bottom: 1px solid #000000;
    height: 80px;
    width: 100%;

    &__playerImg__cont {
      height: 80px;
      width: 100%;
      position: relative;

      .img {
        height: 55px;
        width: 55px;
        border-radius: 50px;
        top: 11px;
        left: 7px;
        position: absolute;
      }
    }

    &__playerText__cont {
      height: 80px;
      width: 100%;
      position: relative;

      .name {
        left: 12px;
        position: absolute;
        font-size: 14px;
        padding-right: 5px;
      }

      .text {
        left: 12px;
        top: 20px;
        font-size: 11px;
        position: absolute;
        padding-top: 8px;
        padding-right: 5px;
        line-height: 13px;
      }
    }
  }
}
//---- //widgets__socialFeed END
\$\endgroup\$
  • 2
    \$\begingroup\$ there are some issues with your scss even if you follow the accepted answer. If you give a real example of a module you have I would like to give suggestions with motivations on why. \$\endgroup\$ – Dejan.S Mar 1 '17 at 15:01
  • \$\begingroup\$ @Dejan.S The question has been reopened. \$\endgroup\$ – 200_success Mar 1 '17 at 15:44
  • \$\begingroup\$ @Dejan.S Keen to hear your bit :) \$\endgroup\$ – danjones_mcr Mar 1 '17 at 16:07
1
\$\begingroup\$

Thinking in re-usable modules you would like to keep things simple and as general as possible with naming. IMO your version of BEM is to specific. I'll try my best to get my point across and guide you.

If we take a look at BEM and what it stands for,

Blocks, Elements and Modifiers

and here is a pretty good summary from Harry Roberts in this blogpost

.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.

So in your case we can remove the following to make it more BEM like and to correct the syntax a bit, both BEM and css selectors (by removing the camleCase).

  • moduleType__moduleName__block__element
  • socialFeed__cardItem__heroImg__cont (real case)

Here you don't need to have moduleType and moduleName as they are kinda the same (what is type, what is name?). So we go with one,

  • social-card(B = block)

next we have _block_ part, heroImg, should be the element in this case, so here we can make it

  • social-card__hero (E = element)

For the purpose of demo we can say that our hero image has a overlay with a default background color that is blue, but we need a red one as well for sale hero images

  • social-card__hero--sale(M = modifier)

Summary of your module could be done with this classes,

  • social-card
  • social-card__hero
  • social-card__hero-image
  • social-card__info
  • social-card__player
  • social-card__player-image
  • social-card__content
  • social-card__content-name
  • social-card__content-text

html with it

<!-- cardItem Start -->
<div class="container-fluid social-card">
  <!-- cardItem Hero Start -->
  <div class="row">
    <div class="col-xs-24">
      <div class="social-card__hero">
        <img src="" class="social-card__hero-image">
      </div>
    </div>
  </div>
  <!-- cardItem Hero End -->
  <!-- cardItem Info Start -->
  <div class="row">
    <div class="col-xs-24">
      <div class="social-card__info">
        <div class="row">
          <div class="col-xs-7">
            <div class="social-card__player">
              <img class="social-card__player-image" src="../assets/img/IMG_0894.jpg">
            </div>
          </div>
          <div class="col-xs-17">
            <div class="social-card__content">
              <h5 class="social-card__content-name">Person Name</h5>
              <p class="social-card__content-text">Consectetuer adipiscing elit. Aenean commo doligula eget dolor...</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- cardItem Info End -->
</div>
<!-- cardItem End -->

So when it comes to sass. I would generally not nest BEM, if done, most one level deep. To use &__some-element to build your BEM is not optimal. Sure you can namespace and save yourself time, but it comes with downsides sides, again, Harry Roberts sums up good with his Code smells in CSS revisited

One less obvious downside, however, is the fact that the string foo-bar now no longer exists in my source code. Searching my codebase for foo-bar will return only results in HTML (or compiled CSS if we’ve checked that into our project). It suddenly became a lot more difficult to locate the source of .foo-bar’s styles.

I found this to be the case for me once in a larger scale project, it was a mess. Of cause it's not the biggest deal of all but looking for something like __image will get a lot of hits instead of hero-slider__image. So writing sass like you would do regular css is ok (plain and one level), sass is great at other things.

Hopes this make sense? Feel free to ask questions.

\$\endgroup\$
  • \$\begingroup\$ I like your approach but I think that in your answer the DOM representation is too deep and you can easily get away with less nested divs. \$\endgroup\$ – Fanis Despoudis Mar 1 '17 at 20:58
  • \$\begingroup\$ @FanisDespoudis Trying to change the structure of the module itself is another review. I agree with it being to nested. But the class names, this approach is BEM. The op version is not (and kinda your answer to). I'm not saying there shouldent be modifications to CSS styles like BEM, but true BEM is not that. \$\endgroup\$ – Dejan.S Mar 1 '17 at 21:25
  • \$\begingroup\$ this is cool man! is it advised that I use the modifiers "--name" and "--text" like that in your answer...? Surely a <h> or <p> tag would be an element? not a modifier? \$\endgroup\$ – danjones_mcr Mar 2 '17 at 14:41
  • \$\begingroup\$ @danjonescidtrix I don't use <h> or <p> as modifiers, I use them as elements, social-card__content-name, there is only one dash "-", using only one dash is for when you have longer selectors, just like social-card, the double underscore "__" seperates block from element, so social-card__hero-image, social-card__hero-image--sale is a modifier. Makes sense? :) \$\endgroup\$ – Dejan.S Mar 2 '17 at 18:56
2
\$\begingroup\$

I've reviewed your code and I can make the following remarks:

While I like the BEM methodology, its not a panacea especially following it to the letter. You must seek simplicity to your code even if that means not following some rules but compiling an pragmatic view of your problem.

In that case you should not add classes if you do not have use cases or rules to apply. Your HTML can be simplified to:

<div class="moduleType">
    <div class="moduleType__moduleName">
       <p class="moduleType__moduleName_element"></p>
    </div>
</div>

and you css will become:

moduleType {
  &__moduleName {
    &_element {
    }
  }
}

one simple rule to follow is: Do not nest selectors more than three levels deep!

Otherwise you will have to much specificity and your rules will be too much coupled with the DOM. Plus no reusability having such a long class names. I would't be bothered to type for example: moduleType__moduleName__block__element__p--modifier1

You want a simple life for you and your fellow colleagues you are going to use your components. Try to use small reusable classes to apply effects and have a simple convention for names.

\$\endgroup\$
  • \$\begingroup\$ thanks for the tips man, out of curiosity - what would you have renamed "moduleType__moduleName__block__element__p--modifier1" to in my case? \$\endgroup\$ – danjones_mcr Feb 23 '17 at 12:33
  • \$\begingroup\$ I would start with a new base. For example if I ever had to target a deep nested element like that. I would add a new logical namespace for the parent like specificElement { &__p {&--modifier{}}} and try to keep the specific elements in separate logical files. What I mean is you should break things up if they become too deeply nested \$\endgroup\$ – Fanis Despoudis Feb 23 '17 at 12:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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