BEM, SASS and Bootstrap: how to mix everything up in a smart way?

Bootstrap is a “HTML, CSS and JS framework for developing responsive, mobile first projects on the web”
SASS is a “powerful professional grade CSS extension language” with a lot of handy features.
BEM is a methodology to solve the “what da fuck I put here in this element’s class now?

For a while I was using LESS — another CSS extension language — and I was happy with it but the design team at hacklab decided to try SASS. I said ok, since I had already used it a long time ago with Rails. And then some shit started to happen.

I always use Bootstrap (and I want to try Foundation someday). I think it comes in handy: a lot of features, saving-time solutions and ready for responsiveness. The caveats was that Bootstrap started with LESS and I started to use Bootstrap with LESS so when I moved everything to Bootstrap-Sass and SASS, some weird things started to happen.

SASS and LESS differ in so many ways.

Variables overwriting

In LESS if you declare a variable with a value and than set another value to that variable later the interpreter will use the last value. In SASS, that doesn’t (-happy-) happen:

LESS: The result is a red background-color

@bg: blue;
body {
background-color: @bg;
}
@bg: red;

Output:

body {
background-color: #ff0000;
}

SASS: The result is a blue background-color

$bg: blue; 
body {
background-color: $bg;
}
$bg: red;

Output:

body {
background-color: blue;
}

And why is this a problem?

I don’t like to change the core files of Bootstrap, so I used to copy the variables.less file to a new directory — usually named bootstrap-theme — and then make any changes I want to but since the variables aren’t overwriting with SASS, we need to pay attention on the import files order.

The directory structure I use is something like this:

 +—— bower_components/
| +—— bootstrap-sass-official/
+—— sass/
| +—— bootstrap-theme/
| +—— _variables.scss
| +—— front-page/
| +—— _carousel.scss
| +—— _highlights.scss
| +—— _news.scss
| +—— main.scss

PS: The directory bower_components is created by Bower — “a package manager (frameworks, libraries, assets, utilities, and rainbows) for the web” — another tool we use at hacklab.

And I use the main.scss file to import all the other files that usually is organized inside contextual folders:

// main.css
// Overriding bootstrap’s variables
@import “bootstrap-theme/variables”;
// Importing Bootstrap-Sass
@import “../bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap”;

Since the order you declare your variables is strictly important with SASS, we need to import our bootstrap-theme’s variables file before the bootstrap-sass-official, other way your customizations will not work properly. And I knocked my head a lot in the desk until I discover it.

Moving on…

Cleaning up css classes

I don’t use Photoshop or Illustrator anymore and almost my work is done directly with HTML/CSS/JS since the start of the project — sometimes I use Sketch 3 to brainstorm some ideas or to create UI elements. Because of that, my code get really messy and confusing and time after time I need to refactor it. But this is something that I like, at the start we almost don’t know how we are going to solve some problems, we cannot see all the patterns and think about all of it prematurely is a waste of time, so I like to do that when the project already had a consistent shape. It is easier and more effective.

So I go from that:

<div id=”social-newsletter”>
<div class=”container”>
<header class=”text-center”>
<h1 class=”bottom top”>Acompanhe as novidades</h1>
</header>
<div class=”row”>
<div class=”social col-xs-6 col-sm-2 col-md-2">
<div class=”facebook block”>
<div class=”centered”>
<a href=”http://www.facebook.com" title=”Facebook”>
<span class=”sr-only”>facebook</span>
<span class=”fa fa-facebook fa-4x”></span>
</a>
</div>
</div>
</div>
<div class=”social col-xs-6 col-sm-2 col-md-2">
<div class=”twitter block”>
<div class=”centered”>
<a href=”http://www.twitter.com" title=”Twitter”>
<span class=”sr-only”>twitter</span>
<span class=”fa fa-twitter fa-4x”></span>
</a>
</div>
</div>
</div>
<div class=”social col-xs-6 col-sm-2 col-md-2">
<div class=”youtube block”>
<div class=”centered”>
<a href=”http://www.youtube.com" title=”YouTube”>
<span class=”sr-only”>youtube</span>
<span class=”fa fa-youtube fa-4x”></span>
</a>
</div>
</div>
</div>
<div class=”social col-xs-6 col-sm-2 col-md-2">
<div class=”instagram block”>
<div class=”centered”>
<a href=”http://www.instagram.com" title=”Instagram”>
<span class=”sr-only”>instagram</span>
<span class=”fa fa-instagram fa-4x”></span>
</a>
</div>
</div>
</div>
<div class=”newsletter col-xs-12 col-sm-4 col-md-4">
<form>
<div class=”block”>
<label class=”centered”>Assine nossa newsletter</label>
</div>
<input type=”email” placeholder=”Insira seu email” class=”col-xs-12 col-sm-12 col-md-12"></input>
<button type=”submit” class=”btn btn-danger col-xs-12 col-sm-12 col-md-12">Cadastrar email <i class=”fa fa-paper-plane fa-2x pull-right”></i></button>
</form>
</div>
</div>
</div>
</div>

To that:

<div class=”social-links js-social-links”>
<header class=”social-links—header”>
<h1>Acompanhe as novidades</h1>
</header>
<div class=”social-links—content”>
<div class=”social-links—link js-social-link”>
<a class=”link—facebook” href=”http://www.facebook.com" title=”Facebook”>
<span class=”sr-only”>facebook</span>
<span class=”fa fa-facebook”></span>
</a>
</div>
<div class=”social-links—link js-social-link”>
<a class=”link—twitter” href=”http://www.twitter.com" title=”Twitter”>
<span class=”sr-only”>twitter</span>
<span class=”fa fa-twitter”></span>
</a>
</div>
<div class=”social-links—link js-social-link”>
<a class=”link—youtube” href=”http://youtube.com" title=”YouTube”>
<span class=”sr-only”>youtube</span>
<span class=”fa fa-youtube”></span>
</a>
</div>
<div class=”social-links—link js-social-link”>
<a class=”link—instagram” href=”http://www.instagram.com" title=”Instagram”>
<span class=”sr-only”>instagram</span>
<span class=”fa fa-instagram”></span>
</a>
</div>
<form class=”social-links—newsletter js-newsletter”>
<label class=”newsletter—label”><span>Assine nossa newsletter</span></label>
<input class=”newsletter—input” type=”email” placeholder=”Insira seu email”/>
<button class=”newsletter—submit” type=”submit”><span>Cadastrar email</span></button>
</form>
</div>
</div>

Expected result:

So in order to refactor the html that way — making it more readable, understandable and semantic — I needed to understand a little bit more how SASS works and the concept behind BEM.

Let’s start with BEM.

BEM: Block. Element. Modifier

BEM stands for “Block. Element. Modifier.” and the ideia is to follow conventions to make everything modular – making it easy to reuse and maintain — and be more descriptive and understandable.

From their website we have:

“A block is an independent entity, a “building block” of an application. A block can be either simple or compound (containing other blocks).”
“An element is a part of a block that performs a certain function. Elements are context-dependent: they only make sense in the context of the block they belong to.”
“A modifier is a property of a block or an element that alters its look or behavior.”

To get the full definition of the methodology and more examples, go here.

The idea is to create a structure likes this:

- block
- block—element
- block—element__modifier

So first we need to understand what we want to achieve and understand the structure of the layout:

Then we start to define our classes inside the context it belongs.

  1. I start creating the context block .social-links
  2. Inside .social-links, I create two other blocks: .social-links—header and .social-links—content
  3. Inside .social-links—header I have just a h1, the only element inside this block
  4. Inside .social-links—content I have four elements (.social-links—link) and one block (.social-links—newsletter)
  5. Inside .social-links—newsletter I have three elements: .newsletter—label.newsletter—input.newsletter—button

Maybe I should use .social-links—newsletter—label.social-links—newsletter—input.social-links—newsletter—button but, since I know that I will not use this block in another place I decided to use a shorter class.

BEM methodology makes easier to create classes, you just need to know the context and then apply the conventions. Pretty easy and straight-forward.

Moving on to Bootstrap.

Bootstrap

Bootstrap has a lot of features, but now I will only show how to use the grid classes with SASS.

In Bootstrap, we have some @mixins to create the grid:

container-fixed()
make-row()
make-xs-column()
make-xs-column-offset()
make-xs-column-push()
make-xs-column-pull()
make-sm-column-offset()
make-sm-column-push()
make-sm-column-pull()
make-md-column-offset()
make-md-column-push()
make-md-column-pull()
make-lg-column-offset()
make-lg-column-push()
make-lg-column-pull()
clearfix()

So with that in mind we can create things like this:


section {
@include make-row();
    article {
@include make-xs-column(12);
@include make-sm-column(7);
@include make-md-column(8);
}
    aside {
@include make-xs-column(12);
@include make-sm-column(3);
@include make-md-column(4);
}
}

And instead of this:

<section class=”row”>
<article class=”col-xs-12 col-sm-7 col-md-8">
Article content
</article>
<aside class=”col-xs-12 col-sm-3 col-md-4">
Aside content
</aside>
</section>

We can do this:

<section>
<article>
Article content
</article>
<aside>
Aside content
</aside>
</section>

A much more cleaner and understanble html.

Moving on to SASS.

SASS

Take a look at this:

<div class=”social-links—content”>
<div class=”social col-xs-6 col-sm-2 col-md-2">
<div class=”twitter block”>
<div class=”centered”>
<a href=”http://www.twitter.com" title=”Twitter”>
<span class=”sr-only”>twitter</span>
<span class=”fa fa-twitter fa-4x”></span>
</a>
</div>
</div>
</div>
</div>

And this:

<div class=”social-links—content”>
<div class=”social-links—link js-social-link”>
<a class=”link—twitter” href=”http://www.twitter.com" title=”Twitter”>
<span class=”sr-only”>twitter</span>
<span class=”fa fa-twitter”></span>
</a>
</div>
</div>

Since the idea is to clean up the html and make it more readable I removed all the bootstrap’s grid classes and inserted it directly on the CSS using the functions @extend and @include from SASS:

.social-links—content {
@extend .container;

.social-link {
@include make-xs-column(6);
@include make-sm-column(2);
}
}

Then I created a @mixin to vertically centralize the icons:

@mixin vertical-align() {
display: block;
&:before {
content: ‘’;
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em;
}
> * {
display: inline-block;
vertical-align: middle;
width: 98%;
}
}

From: Centering in the Unknown | CSS-Tricks

This way I can do that:

.social-links—content {
@extend .container;

.social-link {
@include make-xs-column(6);
@include make-sm-column(2);
a {
@include vertical-align();
}
}
}

And remove the div.block and div.centered from the html:

<div class=”social col-xs-6 col-sm-2 col-md-2">
<div class=”twitter block”>
<div class=”centered”>
<a href=”http://www.twitter.com" title=”Twitter”>
<span class=”sr-only”>twitter</span>
<span class=”fa fa-twitter fa-4x”></span>
</a>
</div>
</div>
</div>
<div class=”social-links—link js-social-link”>
<a class=”link—twitter” href=”http://www.twitter.com" title=”Twitter”>
<span class=”sr-only”>twitter</span>
<span class=”fa fa-twitter”></span>
</a>
</div>

And that is how I achieved a much more cleaner, semantic and understandable html.


First published on andersonorui.com

Like what you read? Give Anderson Orui a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.