A picture of myself

Atanas Stanilov

Part-time web developer. Full-time superhero.

Write SASS/CSS with style

IN: SASS/CSS
Jun 26th 20207 min read

Let me show you some basic tips on how to write exquisite stylesheets with SASS/CSS that are developer-friendly. It's not much but it's honest work 🤷‍♂️

BEM to the rescue

Each one of us has reached the point where we spend more time on cooking class names, rather than writing actual code. Also, the bloating mess you can create with applying incoherent names is significant. And thus, these problems led to the creation of BEM(Block, Element, Modifier) methodology. It's goal is to give CSS and HTML a better relationship and to unify class names we give.

In a few words the convention is simple, we give certain block a name, then every child element's name of this block is formed using their parent's name, while element modifiers are optional and follow the same naming idea. The pattern looks like this block-name__element-name--modifier. You might as well use '_' as a name separator and modifier, but the pattern we've seen is the one I think works best. It gives us a better distinct between different objects.

For example, we might have an HTML like this:

<button class="btn btn--rounded btn--dark">
    <span class="btn__text btn__text--uppercase">Save</span>
</button>

Simple and descriptive. BEM in it's full potential.

The dark side of BEM principles

But, let's see what happens if our HTML has more deeply nested components and we follow the convention completely:

<header class="site-header">
    <a class="site-header__link">
        <img src="/assets/images/site-logo.png" class="site-header__link__logo site-header__link__logo--shrink" />
    </a>
    <ul class="site-header__menu-list">
        <li class="site-header__menu-list__list-item">About</li>
        <li class="site-header__menu-list__list-item">Products</li>
        <li class="site-header__menu-list__list-item">Contact us</li>
    </ul>
</header>

Take a look at the list item in <ul> tag. We can already guess where this is going to lead us. The pitfall of BEM. And this structure is not even something complex. If we continue to follow this method all the way to the deepest element, we're going to have a class name that's bigger than the element itself. Only by creating two levels nesting, we managed to fabricate an abomination of a class site-header__menu-list__list-item, which is very descriptive, but hurts the eye only by looking it, even more than that it will make our CSS selectors a hell of a job.

From this point on we need to break the rules of the convention, in sake of sanity. But it's a matter of personal choice how to do it. How I like to proceed in such cases is to reduce to maximum of two element names, by removing ones from left to right. The idea is to appoint the parent element of the one we currently create, as a block element and start naming from there.

Taking the above example, it will now look like this:

<header class="site-header">
    <a class="site-header__link">
        <img src="/assets/images/site-logo.png" class="site-header__link__logo site-header__link__logo--shrink" />
    </a>
    <ul class="site-header__menu-list">
        <li class="menu-list__list-item">About</li>
        <li class="menu-list__list-item">Products</li>
        <li class="menu-list__list-item">Contact us</li>
    </ul>
</header>

We can progressively enforce this breaking of rules and you will have BEM without bloating your code. However, such solution is not perfect. It makes it easier to reach a point where we have duplicated class names, in different parent elements. But for the work I've done, it has only helped me in lieu of hindering the development.

SASSy with BEM

If you are a fan of SASS, you probably use it coupled with BEM too. And having those two together, you can effortlessly write handy and short style rules.

.site-header {
    display: flex;
    justify-content: space-between;
    &__link {
        font-size: 14px;
        text-decoration: none;
        color: black;
        &__logo {
            height: 30px;
            width: 30px;
            &--shrink {
                height: 20px;
                width: 20px;
            }
        }
    }
}

Which is great! Many prefer using SASS for how easy it is to nest rules. No more repeating of parent class names. With just a couple of lines we applied rules for the block site-header, the element site-header__link, it's child element site-header__link__logo and it's modifier site-header__link__logo--shrink.

By implementing BEM methodology with SASS we can nest selectors as much as HTML elements we have. And that, my dear friends, might be a bad practice.

Of course again it's a matter of choice, but when you create a web app with many SASS files and styles, you start forgetting where you put what. So, you end up reaching out for any kind of search tool to find that portion of code, which applies the rules. And the easiest way to do that is to copy the class name from the HTML and paste it in the search box. Having written our styles like in the example above, if we try to search for site-header__link__logo, the result will give us nothing. Such situation is mostly common when dealing with legacy projects.

So, to prevent this, we'll refactor the above snippet:

.site-header {
    display: flex;
    justify-content: space-between;
    .site-header__link {
        font-size: 14px;
        text-decoration: none;
        color: black;
        .site-header__link__logo {
            height: 30px;
            width: 30px;
            &--shrink {
                height: 20px;
                width: 20px;
            }
        }
    }
}

I leave the modifiers, because the element's name is there for us, following BEM methods we never use the first alone. The HTML will have class="site-header__link__logo site-header__link__logo--shrink", so we can easily grab the name we need and search with it.

Nesting styles can be bad

The subtitle speaks enough. However, I don't neglect or negate nesting styles. I simply propose to do it only when extremely necessary - like when we have to overwrite styles and we need more selector specificity, or we have a small, capsulated element(fancy button, title, link, etc.). The reason behind this is that as developers, we often have to reuse components/elements/code in different places. And making every page's styles deeply nested, hinders the idea.

Our refactored SASS example will look like this:

.site-header {
    display: flex;
    justify-content: space-between;
}
.site-header__link {
    font-size: 14px;
    text-decoration: none;
    color: black;
}
.site-header__link__logo {
    height: 30px;
    width: 30px;
    &--shrink {
        height: 30px;
        width: 30px;
    }
}
.site-header__menu-list {
    display: flex;
}
.menu-list__list-item {
    margin: 0px 10px;
    text-transform: uppercase;
}

Now we can successfully reuse parts of our html wherever needed in the project.

Selectors ordinance

If you take a closer look the example above and the html structure at the beginning, you'll probably notice a structural connection. This is one of the main principles I like to strictly pursue when creating style rules. The selectors follow the HTML elements from top to bottom.

site-header
site-header__link
site-header__link__logo
    site-header__link__logo--shrink
site-header__menu-list
menu-list__list-item

This principle provides a better look at the styles in the SASS file and helps navigate us in the whole website structure. You might have already used this, if you create css/sass files synchronously with the HTML, but what I'm trying to enforce is to follow this method even if we have to refactor some code afterwards.

Rules that matter

Not only selectors can have ordinance. In the process of developing stylesheets, what I like to do is distinguish style rules and arrange them in a proper way. It's simple, we just put the "main" rules on top and "lesser" ones below. But, how do we rank them? By the way they visually change the layout of the component(sort of). This doesn't mean that background property is the most major. We start with the definition of the type of rendering box of an element - display. Let's see an example of ordered styles and you'll quickly get a hang of it.

Let's say we have this style:

.overlay-popup {
    display: flex;
    justify-content: center;
    align-items: center;
    position: fixed;
    bottom: 50px;
    right: 50px;
    height: 45px;
    width: 150px;
    font-size: 12px;
    letter-spacing: 1.2px;
    padding: 10px;
    border: 1px solid #ebebe0;
}

By putting display: flex on top, followed by justify-content and align-items(all flexbox related) we can easily see how the element is formed at first glance. Not only ordered, but rules are also grouped this way. After that - position: fixed and bottom, right properties tell us how and where it is positioned. You can choose to switch the order of display and position. It's a matter of personal preference. If the element is missing these two properties, I like to put font-size on top. This way we can spot the rules that matter at first glance.

There, now it's easier to write structured, ordered and serviceable stylesheets. Thank you for reading 🖖


Don't hesitate to contact me to report any mistakes or just to say hi.

#sass #css

NextPrev

...

Copyright © 2021, Atanas Stanilov

Made with lots of and ❤️

Contact me