Writing consistent and readable CSS that will scale well is a challenging process. Especially when the style sheets are getting larger, more complex, and harder to maintain. One of the tools available to developers to write better CSS are preprocessors. A preprocessor is a program that takes one type of data and converts it to another type of data, and in our case CSS preprocessors are preprocessing languages which are compiled to CSS. There are many CSS preprocessors that front-end developers are recommending and using, but in this article we will focus on Sass. Let’s see what Sass has to offer, why it is a preferable choice over other CSS preprocessors, and how to start using it in the best way.

What Is Sass and Why Should You Use It?

For those of you who don’t know what is Sass, the best starting point is to visit the official Sass webpage. Sass is an acronym for Syntactically Awesome StyleSheets, and is an extension of CSS that adds power and elegance to the basic language.

With Sass (Syntactically Awesome StyleSheets) your CSS code will be also awesome.

With Sass (Syntactically Awesome StyleSheets) your CSS code will be also awesome.

Sass is a CSS preprocessor with a lot of powerful features. The most notable features are variables, extends, and mixins.

Variables store information that can be reused later, like colors or other commonly used values. Extends help you create “classes” that allow inheritance for the rules. Mixins, you can think of like “function”. Sass also has some other amazing features in comparison with other preprocessors, like the use of logic statements (conditionals and loops), custom functions, integration with other libraries like Compas, and many more. These features alone can help you and your team to be more productive and to write better CSS in the end.

Why You Need a CSS Style Guide

Unfortunately, even preprocessors can’t fix everything and help you write good CSS code. The problem every developer is facing is that current web applications are becoming bigger and bigger. That’s why code needs to be scalable and readable, and needs to avoid spaghetti code and unused lines of it. To avoid mentioned problems, some sort of standard for your team in the daily work is needed. What is spaghetti code, and how does it it happen? Spaghetti code is a name for bad, slow, repetitive, and unreadable code. When a team writes big applications without defined guidelines or standards in place, each developer writes what he needs and how he wants. Also when developers are writing a lot of bug fixes, hotfixes, and patches, they tend to write code that will solve the problem but don’t have time to write the code in the best way. In these situations, it is very usual to end up with lots of lines of CSS that are not used in any sector of the application any more. Developers don’t have enough time to clean the code, and they are forced to publish the fix as quickly as possible. Another reocurring situation is that to fix broken things quickly, developers use a lot of !important, which results with very hacky code that is hard to maintain, it results with a lot unexpected behaviors, and needs to be refactored later. As mentioned already, as the code grows the situation becomes only worse.

The idea of this article is to share rules, tips, and best practices to write a better Sass. Grouping together those Sass tips and best practices can be used as a Sass style guide. This style guide should help developers to avoid situations mentioned above. Rules are grouped into logical segments for easier referencing, but in the end you should adopt and follow them all. Or at least, most of them.

Style Guide

The set of rules and best practices in this style guide are adopted based on experience working with a lot of teams. Some of them come from trial by error, and others are inspired by some popular approaches like BEM. For some rules there is no specific reason why and how they were set. Sometimes having the past experience as the only reason is enough. For example, to make sure that the code is readable it is important that all developers are writing the code in the same way, thus there is the rule to not include spaces between parentheses. We can argue if it is better to include the space between parenthesis or not. If you think that it looks better when there are spaces between parenthesis, adjust this style guide and rules by your preferences. In the end, the main goal of the style guide is to define rules, and to make the developing process more standard.

Main goal of the style guide is to define rules, and to make the developing process more standard.

Main goal of the style guide is to define rules, and to make the developing process more standard.

General CSS Rules

General rules should always be followed. They are mostly focused on how Sass code should be formatted to bring consistency and readability of the code:

  • For indentation, use spaces instead of tabs. The best practice is to use 2 spaces. You can run your own sacred war with this option, and you can define your own rule and use either tabs, or spaces, or whatever suits you best. It is only important to define a rule and follow that rule while being consistent.
  • Include an empty line between each statement. This makes the code more human readable, and code is written by humans, right?
  • Use one selector per line, like this:
selector1,
selector2 {
}
  • Do not include a space between parentheses.
selector {
   @include mixin1($size: 4, $color: red);
}
  • Use single quotes to enclose strings and URLs:
selector { font-family: ‘Roboto’, serif; }
  • End all rules with a semicolon without spaces before:
selector {
  margin: 10px;
}

Rules for Selectors

Next we are following with a set of rules to use when dealing with selectors:

  • Avoid the use of ID selectors. IDs are too specific and used mostly for JavaScript actions.
  • Avoid !important. If you need to use this rule, it means that something is wrong with your CSS rules in general, and that your CSS is not structured well. CSS with many !important rules can be easily abused and ends up with messy and hard to maintain CSS code.
  • Do not use child selector. This rule shares the same reasoning as the ID one. Child selectors are too specific and are tightly coupled with your HTML structure.

If you are using !important a lot in your CSS, you are doing it wrong.

If you are using !important a lot in your CSS, you are doing it wrong.

Keep Your Sass Rules in Order

It is important to keep consistency in the code. One of the rules is that you need to keep the order of rules. This way other developers can read the code with much more understanding, and will spend less time finding their way around. Here is the proposed order:

  1. Use @extend first. This let you know at first that this class inherits rules from elsewhere.
  2. Use @include next. Having your mixins and functions included at top is nice to have, and also allows you to know what you will be overwriting (if needed).
  3. Now you can write your regular CSS class or element rules.
  4. Place nested pseudo classes and pseudo elements before any other element.
  5. Finally, write other nested selectors like in the following example:
.homepage {
  @extend page;
  @include border-radius(5px);
  margin-left: 5px;
  &:after{
    content: ‘’;
  }
  a {
  }
  ul {
  }
}

Some naming conventions

Naming conventions part of the style book is based on the two existing BEM and SMACSS naming conventions that became popular amongst developers. BEM stands for Block, Element, Modifier. It was developed by the YANDEX team, and the idea behind BEM was to help developers understand the relationship between HTML and CSS in the project. SMACSS on the other hand stands for Scalable and Modular Architecture for CSS. It is a guide to structure CSS to allow maintainability.

Inspired by them, our naming conventions rules are as follows:

  • Use prefix for each type of element. Prefix your blocks, like: layouts (l-), modules (m-), and states (is-).
  • Use two underscores for child elements for every block:
.m-tab__icon {}
  • Use two dashes for modifiers for every block:
.m-tab--borderless {}

Variables

Use variables. Start with the more general and global variables like colors, and create a separate file for them _colors.scss. If you notice you are repeating some value over the style sheet multiple times, go and create a new variable for that value. Please DRY. You will be grateful when you want to change that value, and when you will need to change it in only one place.

Also, use a hyphen to name your variables:

$red : #f44336;
$secondary-red :#ebccd1;

Media Queries

With Sass you can write your media queries as element queries. Most of the developers write media queries in a separate file or at the bottom of our rules, but that is not recommended. With Sass you can write things like the following example by nesting media queries:

// ScSS
.m-block {
  &:after {
    @include breakpoint(tablet){
      content: '';
      width: 100%;
    }
  }
}

This generates a CSS like this:

// Generated CSS
@media screen and (min-width: 767px) {
  .m-block:after {
    content: '';
    width: 100%;
  }
}

This nested media queries rules allow you to know very clearly what rules are you overwriting, as you can see in the Sass snippet where named media queries are used.

To create named media queries, create your mixin like this:

@mixin breakpoint($point) {
  @if $point == tablet {
    @media (min-width: 768px) and (max-width: 1024px) {
      @content;
    }
  } @else if $point == phone {
    @media (max-width: 767px) {
      @content;
    }
  } @else if $point == desktop {
    @media (min-width: 1025px) {
      @content;
    }
  }
}

You can read more about naming media queries in the following articles: Naming Media Queries and Write Better Media Queries with Sass.

Other Considerations

In the end, here are some other considerations that you should also keep in mind and follow:

  • Never write vendor prefixes. Use autoprefixer instead.
  • Use maximum three levels of deep in nested rules. With more than three nested levels, the code will be difficult to read, and maybe you are writing a crappy selector. In the end, you are writing CSS code to couple with your HTML.
.class1 {
   .class2 {
       li {
           //last rules
       }
    }
}
  • Don’t write more than 50 lines of nested code: Or better, don’t write more than X lines of nested code. Setup your own X, but 50 looks like a good limit. If you pass that limit maybe the block of code will not fit in your text editor window.
  • Write a main file where you will import all of your blocks, partials, and configs.
  • Import vendor and global dependencies first, then authored dependencies, then layouts, patterns, and finally the parts and blocks. This is important to avoid mixed imports and overwrite of rules, because the vendor and global rules can’t be managed by us.
  • Don’t be shy and break your code in as many files as possible.

Conclusion

The idea behind this style guide is to give you some advice on how to improve the way you are writing your Sass code. Please keep in mind that even if you are not using Sass, the provided tips and rules in this style guide are also applicable and recommended to follow if you use Vanilla CSS or another preprocessor. Again, if you don’t agree with any of the rules, change the rule to fit your way of thinking. In the end, it is up to you and your team to either adapt this style guide, use some other style guide, or create a completely new one. Just define the guide, and start writing an awesome code.

About the author

Matias Hernandez, Chile
member since March 11, 2014
Matías is an experienced software engineer with more than 7 years of work as a front-end developer with several companies all around the globe on a variety of challenging projects. Currently, he works as mainly as a JavaScript developer and project manager. [click to continue...]
Hiring? Meet the Top 10 Freelance Front-End Developers for Hire in September 2016

Comments

Greg Garrison
Hi Matias - great article and introduction to modern styling! I think most designer/developers dream of the new project where they're starting from scratch and can do all these things correctly. Most of us, unfortunately, end up in situations where we're working with legacy code, sometimes a LOT of it. I work with an online learning management system and it has two monolithic CSS style sheet files that, combined, are over 1MB and have somewhere between fifteen- and twenty-thousand rules. The rules are hyper-specific, misspelled, overlapping, contradicting and every other kind of bad you can imagine. The markup on most pages isn't terrific, either, but it's in better shape. It doesn't use a preprocessor but I'm intrigued by that concept. How would you recommend tackling a project like that? Start with the markup? Get rid of the CSS completely and style from scratch? I don't necessarily need to do much re-design right now, but want to be able to down the road and that's basically impossible with the situation right now. Thanks for any tips!
brianm101
@Greg hardly modern its as old as software (nearly) - its just the basics that keep being forgotten, style guides or rules (if you are less pink and fluffy) are vital no matter what language or environment you are using. It hardly matters what (spaces ort tabs for example) its the adherence to them that is the big problem! Articles like this one just need to be repeated as suitable intervals!
xavier
Hi Matias, I got to many limitations with placeholder, I'm using the mixins to extend my class, but I agree with the ideas and the organisations. In the real world, those are too limited.
Matías Hernández Arellano
Hey @greg_garrison:disqus . As you said, unfortunately we end up in very uncomfortable situations working with legacy code or bad code. Currently I'm working in a project with lot of Legacy code (SaSS and JS code). We tackle this with some new rules and approaches for the coding process, to create better new code. To add new features we write new code in a new folder structure. For legacy code we have "refactor days" where we change that ugly code for the new one. So get rid of the CSS completely and start from scratch sounds good but is not very doable and maybe you will end spending more time writing everything again. Just take little parts/modules/blocks, update the markup (if is needed) and refactor just that scss/css code with new rules based on some guideline (maybe this) or set of new rules. The team need to get used to this new way of work.
Greg Garrison
Thanks a lot for sharing your experience and advice!!
Konstantin Gorbunoff
Hi. .homepage { @extend page; Error or not ?
comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering and design posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
You can edit your subscription preferences here.
Trending articles
Relevant technologies
About the author
Matias Hernandez
JavaScript Developer
Matías is an experienced software engineer with more than 7 years of work as a front-end developer with several companies all around the globe on a variety of challenging projects. Currently, he works as mainly as a JavaScript developer and project manager.