(S)CSS Best Practices That You Have Not Yet Known
Even if you now build your applications using a popular framework, like React, Angular or Vue.js, you still need to add some styles to them. Depending on the technology you use, you need to write your styles in a specific way. For example for React, due to it’s component nature, it’s better to write styles using CSS modules. If you want to use brand new CSS features, it would be wise to use CSSNext. Don’t forget about good ol’ CSS preprocessors, like Sass or LESS. You may think - so many tools, I bet writing styles is different for each of them. Yes, you’re right. But the basics are the same.
In this article, I want to present a few nice tips for writing robust and maintainable CSS, regardless if you are fan of using CSS modules or Sass/LESS. These tips are presented in SCSS syntax, so if you need some introduction to Sass, here’s a good place to start. If you use plain CSS, extended by CSS Next, this article is for you as well. These basic concepts can be easily used in other CSS tools or preprocessors.
Structure your styles
Well-thought folder structure helps with maintaining your project. The same goes for your styles. It’s important to divide your code according to elements they refer to. Storing all your rules in one huge styles.scss file would cause troubles for sure. Especially if you want to scale up your project and add new components.
In terms of project’s scaling it’s vital to set proper styles structure. You should focus on providing structure, which will order your files according to components you use in your project. I suggest you to separate base styles from component’s and theme’s styles. Also it makes sense to combine all mixins and variables in one folder, depending on theirs role.
Below is an example folder structure:
Name the colors
So, you have a website design and you want to start with coding layout. What would be a wise approach for managing colours in your project? Simply you can write colour values directly in style rules. But this approach could be troublesome in the future. Fortunately, both CSS and Sass gives us variables.
In Sass you can store any value as variable, so it’s reasonable to store colour value as variable. Mostly, we use HEX (hexadecimals) to define colour value. For human, HEX looks like cypher, because it’s a format designed for computers. It’s hard to tell what colour is written as #7fffd4 or #ffd700 (if you understand them, it’s possible that you would fail CAPTCHA test). The first one is aquamarine and the second is gold. Wouldn’t it be easier to have those colours named in that manner?
Some of colours have specific roles in website design. One colour can be used as brand colour, the other one is meant for background. Although, we write code for the browser, we should build some robust structure for our colours. It’s good to have some help from the designer. If you can’t convince him to describe colour palette, still you can do it yourself.
Firstly, you should begin with naming your colours. Definitely, it’s hard to translate HEX value to human-readable name. Luckily, we have proper tools for that. I use Name that Color website, but you can use any other tool that you prefer.
When you have names for your colours, you can assign roles to them. You should define which colour is used as primary and which one is a secondary. If you are not sure how to set roles for your colours, you can grab some inspiration from Bootstrap’s colour scheme.
Here’s an example colour setup:
Flatten nested declarations
Using CSS preprocessor not only adds some useful functions to your toolset, but also helps with code organisation. The best example is styles’ declaration nesting. In Sass it’s possible to nest selector in other selectors, so that you can see what’s the relation between them. It’s really powerful feature, so it can be overused pretty easily.
I suggest you to not go more than 3 levels deep. This rule applies both for selectors specificity and selectors nesting in CSS preprocessors. Going beyond that limit not only increases selector’s strength, but also can make reading your code more difficult.
See an example below:
Don’t overuse parent’s reference
In Sass it’s possible to get reference of selector’s parent. In combination with nesting, you can define rules which need parent’s selector. For example:
& can be misleading. Here’s an example of bad usage of that selector:
As you can see, the ampersand selector can add unnecessary complexity to your styles and makes reading your code difficult.
Write properties in meaningful order
You don’t have to sort your properties, but you should. Properly sorted properties indicate that your code style is consistent. What’s more, it makes scanning your code more convenient. There is no one source of truth in terms of properties sorting. You can sort them alphabetically or by any other preference. I use slightly modified rules included in formatting guidelines of SMACSS methodology. Here’s my recommended order:
- Box (position, display, width, margin, etc.)
- Other (Alphabetically)
Use class’ naming convention
When your project grows, styles can get pretty messy. Especially, when you need to extend existing rules. Unfortunately, CSS doesn’t provide any helpful mechanisms, which would prevent from the namespace clash. In other words, all styles written in CSS are global, so it’s highly possible that you may unexpectedly overwrite some properties.
Due to the cascading nature of CSS, it’s important to define very specific selectors. It doesn’t mean that you should use selectors with high specificity. You need to avoid general selectors, like tag selectors, when you want add styles for particular element.
Here’s an example:
Hopefully, writing maintainable styles is not that hard, when we can use one of popular class naming conventions - BEM, OOCSS or SMACSS. I prefer BEM, which is a very popular methodology created by Yandex developers. Its name is an acronym of block, modifier and element words. If you are not familiar with BEM, I suggest you to read its documentation.
Here’s our example, after bemification:
Write descriptive media queries
Media queries are the most important part of responsive website development. Thanks to them, we can define styles for different resolutions and change layout according to user’s device. In CSS, media queries are a set of rules, which are tested against user’s browser. When fulfilled, styles defined in media query block are applied to the website.
You can target various devices using queries, which describe types and features of medias. Due to the many rules’ combination, media query can become complex pretty easily.
To make media queries more developer-friendly we can assign it’s rules to a variable. In Sass it’s possible to use string as normal CSS code using the interpolation braces
The same trick we can use for other at-rules. It can be handy for defining complex
Add modular styles
CSS has a set of very useful selectors. In most cases you use class selector or descendant selector. But there is one other selector, which is effective for writing modular styles. It’s the adjacent sibling selector, known also as the plus selector.
Let’s imagine that you would like to write styles which are applied only when some element precedes selector’s element. For example, you can add margin to article’s text, when it has a title. Here’s how you can do it:
It’s a very convenient way of defining styles, and my favorite one. But there are some tradeoffs. First of all, it’s not the most performant selector. If you care more about performance rather than modularity, you shouldn’t use it. Secondly, using sibling selector increases specificty, so it might be hard to overwrite its styles later. After all, it’s worth to use it, when you want to apply styles based on elements’ presence.
Now, you know how to write readable, maintainable and modular styles. If you need more advices how to write styles to be proud of, see these articles:
- Sass Color Variables That Don’t Suck by Landon Schropp
- Advanced SCSS, or 16 Cool Things You May Not Have Known Your Stylesheets Could Do by Jarno Rantanen
- Adjacent sibling selector specs by W3C
- Modular CSS naming conventions by John W. Long
- Responsive Web Design in Sass by Mason Wendell
- How to structure a Sass project by John W. Long