Introducing Modular CSS with BEM

Contents of the Talk

  • Quick overview of CSS
  • Potential CSS Pitfalls
  • About BEM naming convention
  • Why use BEM?
  • How to use BEM

Quick overview of CSS

Cascading Style Sheets

Without CSS

With CSS

The Cascade

Two things in CSS help determine which style(s) an element inherits.

  1. Specificity
  2. Where the style rule lives in the stylesheet file

Specificity


p a { color: red; }
a { color: blue; }

This link will be red

Order


a { color: red; }
a { color: blue; }

This link will be blue

Specificity

Source: https://stuffandnonsense.co.uk/archives/images/specificitywars-05v2.jpg

Trouble in (CSS) Paradise

!important


#creature.equine.unicorn .body mane hair { color: blue; }
#creature.equine.horse .body mane hair { color: brown; }
#creature.equine.zebra .body mane hair { color: black; }
Red hair for all? OK:
#creature hair { color: red !important; }
Oh, but horses need green hair:
#creature.horse hair { color: green !important; }
... and so on.

Long, complex selectors

HTML



  



  

                

CSS


// relatively simple selector
.horse mane {
  color: brown;
}

// complex selector
creature#unicorn.equine.unicorn mane {
  color: black;
}
                

The client says hey, all horses and unicorns need white manes.


.equine mane {
  color: white !important; :(
}
            

See the Pen BEM - Holy Selectors Batman by WebAdvanced (@WebAdvanced) on CodePen.

Inline styles


              
            

These can only be overwritten with !important

So how do we fix it?

BEM to the rescue!

(Also, just don't use inline CSS.)

Block

Element

Modifier

Why use BEM?

  1. Modular
  2. Reusable
  3. Loosely tied to structure

Naming

Blocks

  • Any combination of letters, digits, and dashes
    
    
  • No tag names, no IDs
    
    // wrong
    div.news-showcase { ... }
    #news.news-showcase { ... }
    
    // correct
    .news-showcase { ... }
    
  • No dependency on any other blocks or elements on the page.
    
    // wrong
    .homepage .news-showcase { ... }
    
    // correct
    .news-showcase { ... }
    

Naming

Elements

  • Block name + two underscores + element name
    
    .news-showcase__item { }
    
  • CSS should not have tag names (e.g. "div") or IDs
    
    // wrong
    div.news-showcase__item { }
    
  • Class should have no dependency on any other blocks or elements on the page.

// wrong
.news-showcase .news-showcase__item { }

// correct
.news-showcase__item { }
          

Naming

Modifiers

  • Block or element name followed by two dashes, then modifier name.
    
    .news-showcase--full-width { }
    .news-showcase__item--large { }
    
  • Keep the original class on the element
    
    
  • Sometimes modifiers may be a dependency for other elements
    
    .news-showcase__item--large .news-showcase__heading { } // headings inside large showcase item
    

Naming

Other

  • Executing javascript?
    
    //HTML
    Watch Video
    
    
    //JS
    $('.js--open-modal').magnificPopup();
    
    
    //No CSS!
    
  • IDs can also be used for this, but a class is nice for a reuseable component that has functionality (such as a rotator or modal popup).

BEM with fake code

See the Pen BEM Presentation - HTML by WebAdvanced (@WebAdvanced) on CodePen.

See the Pen BEM Presentation - CSS by WebAdvanced (@WebAdvanced) on CodePen.

SASS Tips

You can group BEM blocks with their elements and modifiers into a tidy package using SASS or LESS.


// The SCSS
.news-showcase {
  ...
  &__item {
    ...
    &--large {
      ...
      .news-showcase__heading {
        ...
      }
    }
  }
  &__heading {
    ...
  }
}

// The Generated CSS
.news-showcase { ... }
.news-showcase__item { ... }
.news-showcase__item--large { ... }
.news-showcase__item--large .news-showcase__heading { ... }
.news-showcase__heading { ... }

General Rules

  • Stick to the naming convention
  • When using SASS/LESS, only nest classes when necessary
  • Avoid IDs/!important in your CSS & inline styles in your HTML
  • Keep your CSS markup-agnostic. CSS shouldn't care if it is on a <div> or a <p>


Let's try to avoid this!

Questions?

Fixing browser bugs