CSS Organisation for a large project

Parham
Code道
Published in
5 min readApr 12, 2018

As a front end developer, you are writing CSS in every project. Depending on the size of the project you will face many challenges in using CSS effectively.

  • Where to put a specific style?
  • What is the selector to use and do I need to be concerned about CSS specificity?
  • What name should I use for my class?
  • I am desperate to fix an issue. Can I override a CSS rule with a more specific selector? Can I use “!important"?
  • Should we use a CSS linter?
  • How do I change the class name on an element without going through vigorous regression testing?
  • Can I benefit from automated CSS testing?

In our recent project we tried to address some of these issues.

My goals are:

  • Easily decide on the new class names.
  • Avoid writing CSS that has side effects.
  • Making sure there is no !important statements.
  • Put CSS as close to its related UI component as possible.

If you have used Angular (2+) you know that framework tries to free you from global CSS and its issues by limiting styles related to a component to that component only. Angular does this by adding attributes to compiled HTML and using those attributes as selectors to limit the scope of your CSS. NEAT!

In many projects we use ionic and this framework is using a different approach to styling. It still uses SCSS, same as Angular but does not apply attribute selectors. Thus anything you write as CSS(SCSS) ends up as global CSS.

The Ionic team says the difference is because there was not a styleSheetUrls config at the time they made this decision and it’s gonna be fixed in Ionic 4.

To achieve my first goal here I am looking for:

  • A naming convention to make it easy for developers in my team on deciding on CSS class names and gives us a bit of consistency across the project.
    BEM comes up if you start looking for CSS naming conventions and although ascetically it doesn’t look appealing I found many good reasons to use it.
  • Make use of best practices to organise CSS in my project while I can enjoy the benefits of SCSS and potentially Angular components to support me.
  • The solution should be easy enough so my team can pick it up by small learning.

Starting with BEM

BEM stands for Block, Element, Modifier and what does that mean?

Block

A block is a component. It’s a little abstract, so let’s use examples instead.
Let’s say you’re building a contact form. In this case, the form can be a block. In BEM, blocks are written as class names, like this:

.form { /* styles */ }

The reason BEM uses a .form class instead of the <form> element is because classes allow for infinite reusability, even if the fundamental element should change in style.

Buttons are good examples of blocks that can contain different possible styles. If you set the background color of a <button> element to be red, all <buttons> are forced to inherit the red background. Following which, you have to fix your code by overwriting your <button> elements.

button {
background-color: red;
}
.something button {
background-color: blue;
}

If styled a button with a .button class instead, you can choose whether to use the .button class on any <button> elements. Then, if you need a different background color, all you do is to change to a new class, say .button--secondary, and you’re good to go!

.button {
background-color: red;
}
.button--secondary {
background-color: blue;
}

Elements

Elements are children of a block. To say that something is an element, you add __element to the block name. So, if you see a class that says.form__row, you’ll immediately know that there’s a row element within the .form block.

<form class="patrol" action="">
<div class="patrol__item">
<!-- ... -->
</div>
</form>
.patrol__item { /* styles */ }

Modifiers

Modifiers are flags that change the appearance of a block. To use a modifier, you add --modifier to the block.

Moving on with the button example from above, the modified button would be named .button--secondary.

<button class="button">Primary button</button>
<button class="button button--secondary">Secondary button</button>
.button {
padding: 0.5em 0.75em;
background-color: red;
}
.button--primary {
background-color: green;
}

Why should we consider BEM?

  1. If we want to make a new style of a component, we can easily see which modifiers and children already exist. We might even realize we don’t need to write any CSS in the first place because there is a pre-existing modifier that does what we need.
  2. If we are reading the markup instead of CSS, we should be able to quickly get an idea of which element depends on another (in the previous example we can see that .patrol__item depends on .patrol, even if we don't know what that does just yet.)
  3. Designers and developers can consistently name components for easier communication between team members. In other words, BEM gives everyone on a project a declarative syntax that they can share so that they’re on the same page.

How to make use of SCSS in this approach

SCSS will let you can have nested blocks, mixins, variables which can be used with BEM but what I am most interested in is to avoid high levels of specificity in my CSS.

If you remember one my goals is to avoid using !important and we have all been there. The best way to guarantee you are not gonna need it is to avoid multi level selectors.

<div class="container">
<div class="title">
<h1>Hello</h1>
</div>
</div>
// Example 1
.container {
title {
h1 {
font-size: 2em;
}
}
}
// Compiled css .container title h1 👎
// Example 2
.container {
&-title {
&-h1 {
font-size: 2em;
}
}
}
// Compiled css .container-title-h1 👍

Example 1 will have a higher level specifity and you are more likely to trap yourself and ending up using selectors with higher specifity or !important to overwrite CSS if needed.

Example 2 still has benefits of using SCSS and not repeating yourself but it’s also a flat selector which is a relief and if you care about performance it’s a little faster when browser queries DOM to style your document.

More to explore

There is more to BEM and there are many corner cases you come across that is not easy to decide on naming. Cases like children of children.

In my next article I will look into more advanced cases using BEM and try to explore using modular CSS approaches like SMACSS and OOCSS and test to see how we can benefit from them in our current projects.

Plus I would like to have a look at CSS in JS approach. This approach is more popular in React community and it’s a interesting one from reusability point of view.

Conclusion

Using a naming convention with SCSS can boost our team productivity and give us a bit more consistency in code.

At the same time there is a little learning curve involved and you need to get used to syntax which can look alien at the beginning.

--

--

Parham
Code道
Editor for

Web & mobile developer, @Auth0Ambassador. Follow me for content on JavaScript, Angular, React, Ionic & Capacitor, Progressive web apps & UI/UX.