Building a website with BEM and SASS: Part 1 – Introduction

Wall of LEGO

Image courtesy of Omar Flores

Both BEM and SASS are great on their own but united they’re like that Avengers film that everyone banged on about.

This post builds upon my discussion about Modular Web Design so if you’ve yet to check that out (shame on you), you can do so now!

Both BEM and SASS are nothing new when it comes to web development and with atomic CSS gaining in popularity it makes me wonder whether this series of posts is a little too late. Regardless, I’m here waxing lyrical about these well-known web practices and you can’t stop me!

The setup

As I said in my previous post, I’m quite fond of coding from scratch and tend to steer clear of automation or design-to-code software but this comes at a cost. It’s time-consuming. But for as long as I’ve been building websites professionally, there have been tools to aid the development process. They just confused the heck out of me during my development infancy. Enter SASS.

SASS is a variation of CSS which makes use of helpful features such as nesting, functions, variables and the separating of styles into multiple stylesheets. In short, it’s bloody handy and it’s the latter that works so well with BEM.

BEM is a CSS naming convention and it’s something that I’ve shunned for many years. Why did I shun it? Because it makes my code look like a hot mess. But after working on a large and unruly project with button classes such as .red .facebook .rounded .yellow-rounded it was time for a change.

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

Phil Karlton

Phil knows what he’s on about. Naming things is a massive pain in the arse. But once I’d swallowed my aversions to BEM, I realised that it is our saviour.

BEM stands for Block Element Modifier and works as such. Your block, in the case a button, has its own class .button. If you want to modify this button you can do so by creating a second class such as .button—-red or .button—-rounded. If you have an element within the button, maybe an icon, you’d create another class .button__icon.

The double dashes denote a modifier whereas the double underscores denote an element.

This doesn’t immediately eliminate the issue I had with my buttons earlier, at least from a point of limiting the number of classes, but it helps make everything more cohesive and manageable. It also drops any dependencies because these are standalone classes.

That’s a very quick overview of both BEM and SASS but how do they marry? Beautifully.

The practice

I mentioned earlier that SASS features nesting and it does so by simply adding a selector within a parent’s curly braces.

.button {

	.red {
		/* Styles */
	}
}

Will compile as:

.button .red {
	/* Styles */
}

This is handy for certain applications but doesn’t necessarily help us with BEM. Well, SASS also makes use of the ampersand symbol when nesting. Unlike standard nesting, the ampersand tells us to append the child selector to its parent. This means we can now do the following:

.button {

	&.red {
		/* Styles */
	}
}

Which compiles as:

.button.red {
	/* Styles */
}

Notice how the spacing has been removed between the .button and .red classes. We’ve now created a selector for an element with the classes .button and .red rather than looking for a .red class nested within an element with the .button class.

Now, this is all well and good but what does it have to do with BEM?

If we break down the BEM convention we have a .block class appended by either a --modifier or an __element. We’ve just seen that using the ampersand in SASS appends the nested selector to its parent so you know what that means! We can do the following:

.block {
	/* Block styles */

	&__element {
		/* Element styles */
	}

	&--modifier {
		/* Modifier styles */
	}
}

Which compiles as so:

.block {
	/* Block styles */
}
.block__element {
	/* Element styles */
}
.block--modifier {
	/* Modifier styles */
}

It’s good, right? It means we can utilise one of SASSs (arguably) most time-saving features to create a load of BEM classes which, in turn, makes our styles less dependent. It’s the best of both worlds! And it doesn’t stop there.

The project

If we jump back to another feature of SASS that I mentioned earlier – separating your styles into multiple files – we can start to build an incredibly easy-to-manage BEM SASS project. Each block can have its own file which will be imported into the master SASS file.

Here’s our simple markup of a login form.

<form class="form card">
	<div class="card__header">
		<h2 class="title title--medium card__title">Log in</h2>
	</div>
	<div class="card__body">
		<div class="form__group">
			<label class="label form__label" for="username">Username</label>
			<input type="text" class="input input--text form__input" id="username" name="username">
		</div>
		<div class="form__group">
			<label class="label form__label" for="password">Password</label>
			<input type="password" class="input input--password form__input" id="password" name="password" minlength="8">
		</div>
		<div class="form__group">
			<input type="checkbox" class="input input--checkbox form__input" name="remember_me" id="remember-me" value="1">
			<label class="label form__label" for="remember-me">Remember me</label>
		</div>
		<div class="form__group">
			<button type="submit" class="button button--primary form__button">Log in</button>
		</div>
	</div>
	<div class="card__footer">
		<a href="#" class="form__link" title="Click here to reset your password">Forgot your password?</a>
	</div>
</form>

I’m using quite a few classes here but broken down they look like so:

.button {}
.button--primary {}

.card
.card__body {}
.card__footer {}
.card__header {}
.card__title {}

.form {}
.form__button {}
.form__group {}
.form__input {}
.form__label {}
.form__link {}

.input {}
.input--checkbox {}
.input--password {}
.input--text {}

.label {}

.title {}
.title--medium {}

When these are listed like so, it makes it easier to see how these can be separated into their own files but for sake of really covering all bases, here’s a screenshot of the project file structure.

SCSS project file structure showing a parent folder named 'scss' with a child folder named 'blocks'. Within the blocks folder are 6 individual .scss files, one for each block referenced above

We’ve now got 6 separate files for each of the blocks referenced above but we need to add them to our master file.

Below is our styles.scss master file which imports all of the other scss files:

// Globals
@import "globals/variables";
@import "globals/mixins";
@import "globals/setup";

// Blocks
@import "blocks/button";
@import "blocks/card";
@import "blocks/form";
@import "blocks/input";
@import "blocks/label";
@import "blocks/title";

Now, when the master file is compiled, it will collect the contents of each of these imported files and merge them into one .css file.

You can use an underscore before the name of any .scss file to show that it’s a partial, i.e. a set of styles which are going to be imported into a master stylesheet as opposed to the file being compiled into its own stylesheet. The underscore isn’t needed when importing these files, assuming you don’t have two files with matching names in the same directory i.e. button.scss & _button.scss but it can be included if you’d prefer.

With the files all linked together, we can now start adding some styles.

Adding the below block of code to the _card.scss file…

.card {
	border-bottom-left-radius: $border-radius-lg;
	border-bottom-right-radius: $border-radius-lg;
	@include box-shadow(1.2em);
	margin-left: auto;
	margin-right: auto;
	max-width: 30em;

	&__body,
	&__footer {
		padding: $card-padding;
	}


	&__header {
		background-color: $primary;
		border-top-left-radius: $border-radius-lg;
		border-top-right-radius: $border-radius-lg;
		color: $secondary;
		padding: #{$card-padding / 2};
		text-align: center;
	}

	&__title {
		margin: 0;
	}
}

will compile like so:

.card {
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
  -webkit-box-shadow: 0 0 1.2em rgba(0, 0, 0, 0.25);
          box-shadow: 0 0 1.2em rgba(0, 0, 0, 0.25);
  margin-left: auto;
  margin-right: auto;
  max-width: 30em;
}

.card__body,
.card__footer {
  padding: 2.5em;
}

.card__footer {
  margin-top: -2.5em;
}

.card__header {
  background-color: #4436EF;
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
  color: #FFF;
  padding: 1.25em;
  text-align: center;
}

.card__title {
  margin: 0;
}

Et voila. We’ve got our first set of BEM classes.

This was a quick, basic, overview of how BEM and SASS work together but it should hopefully highlight just how powerful the two can be. I’ll cover each step of the process in more detail, in future parts, but in the meantime, you can head over to https://sass-lang.com/ and find out more about SASS.

In the next part, we’ll set up our project and begin setting up the layout of a simple web page based on a design.

If you have any questions drop a comment below or hit me up on Twitter @KieranMcClung

Related

All good things come to an end.

© Kieran McClung, 2019 Privacy & Cookies