CSS Specificity

Or: How I learned to stop worrying and love the BEM

-- Phil Karlton

"There are only two hard things in Computer Science: cache invalidation and naming things."

Why is naming hard in CSS?

  • Collaboration

  • CSS Specificity

CSS Specificity

h1 {
    color: blue;
}

h1 {
    color: black;
}
<h1>Title</h1>

In general, later CSS rules override earlier ones.

CSS Specificity

.title {
    color: red;
}

h1 {
    color: black;
}
<h1 class="title">Title</h1>

Order is overruled by "specificity," which is determined by the selector you use (element, class, id, etc.)

h1.title {
    color: blue;
}

Combining multiple selectors adds their specificity "score" together.

CSS Specificity

#foo {
    color: blue
}

.bar {
    color: red;
}

h1 {
    color: black;
}

h1 {
    color: #BADA55 !important;
}

Inline Styles

<h1 style="color: green;">Title</h1>

IDs

Elements

Classes

!important trumps everything else

CSS Specificity

#foo {
    color: blue
}

.bar {
    color: red;
}

h1 {
    color: black;
}

section.article .title {
    color: purple;
}

1000

<h1 style="color: green;">Title</h1>

0100

0001

0010

Specificity can be calculated using a "point" system.

0021

CSS Specificity

BEM

BEM is a naming convention which helps you keep your CSS specificity "flat"

Advantages

  • It's descriptive
    • Class names hint at the markup structure
  • Separation of concerns
    • Everything you select in your CSS has its own class
    • Modifiers represent tweaks
  • One CSS selector won't overwrite another
    • Nearly all rules have 0010 specificity

BEM

BEM is a naming convention which helps you keep your CSS specificity "flat"

Disadvantages

  • It's ugly
  • It could be more descriptive
    • Namespacing enhances this

BEM

BEM stands for Block Element Modifier

Block: An abstract component

Element: A descendant or relative of the block, which helps form the block

Modifier: A different state or version of a block or element

.person {} // Block
.person__hand {} // Element
.person--female {} //Modified block

BEM

.person {} // Block
.person__hand {} // Element
.person--female {} //Modified block


.person__hand--left {} // Modified Element

.person--female__hand {} // Element of a modified (type of) block
.modal {} // A modal popup
.modal--open {} // Styles the modal when open 
.modal__header {} // The header of a modal
.button {} // Basic button styles (can include defaults)
.button--alert {} // Styles to make the button red
.button--small {} // Styles to make the button small

In practice...

Or...

BEM

.modal {
    display: none; // Hide by default
    width: 500px; // Base styles, etc.
}
.modal--open {
    display: block; // Show the modal.
}
.modal__header {
    text-transform: uppercase; // Modal headers are uppercase
}

CSS

<div class="modal modal--open">
    <h1 class="modal__header">Signup Successful!</h1>
    <p>You are now a member.</p>
</div>

HTML

BEM

.button {
    padding: 10px; // Padding around text
    background-color: grey; // Default background color
    color: black; // Default text color
}
.button--success {
    background-color: green;
    color: white;
}

.modal__button {
    float: right; // Modal buttons are on the right side
}

CSS

<div class="modal modal--open">
    <h1 class="modal__header">Signup Successful!</h1>
    <p>You are now a member.</p>

    <button class="modal__button button button--success">DONE</button>
</div>

HTML

Separation of concerns!

BEM

<div class="modal modal--open">
    <h1 class="modal__header">Signup Successful!</h1>
    <p>You are now a member.</p>

    <button class="modal__button button button--success">DONE</button>
</div>

HTML

This represents both a feature and a limitation of BEM.

A BEM class cannot have more than one element or one modifier, so at some point you must name a new block.

<div class="modal modal--open">
    <h1 class="modal__header">Signup Successful!</h1>
    <div class="modal__body">
        <p class="modal__body__paragraph">This is not BEM!</p>
        <p class="modal__paragraph">This is BEM.</p>
    </div>
</div>

When not to BEM

<div class="header">
    <img class="site-logo" src="logo.png">
</div>
<div class="header">
    <img class="header__logo" src="logo.png">
</div>

Is the site-logo styled a certain way because it's in the header? Probably not, but if so...

Ask yourself: 

BEM is just a way of writing classes which imply structure (with elements) and variation (with modifiers). 

Not every class name needs __ or --.

Let it help you, not hinder you!

BEM & Sass

.modal {
    // Base modal styles

    &--open {
        // .modal--open styles
    }

    &__header {
        // .modal__header styles
    }
    &__button {
        // .modal__button styles
    }
}

Sass's ampersand (&) feature makes BEM super easy to write and read.

<div class="modal modal--open">
    <h1 class="modal__header">Signup Successful!</h1>
    <p>You are now a member.</p>

    <button class="modal__button button button--success">DONE</button>
</div>
.button {
    // Base button Styles

    &--success {}
    &--warning {}

    &--small {}
    &--large {}
}

The End

  • https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
  • http://getbem.com/introduction/
  • https://css-tricks.com/bem-101/
  • https://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/

CSS Specificity and BEM

By James TW

CSS Specificity and BEM

  • 2,727