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.
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.
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.
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:
- Use
@extend
first. This let you know at first that this class inherits rules from elsewhere. - 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). - Now you can write your regular CSS class or element rules.
- Place nested pseudo classes and pseudo elements before any other element.
- 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.
NOTE : This article is authorized to republish here by toptal.