CSS Preprocessors: What are they and how to use them?

CSS preprocessors are tools that extend the functionality and syntax of CSS, making it more expressive, powerful, and maintainable. A preprocessor allows you to write code in a special language, such as Sass, Less, or Stylus, and then compiles it into plain CSS that browsers can understand.

In this article, you will learn:

  • What are the benefits and drawbacks of using CSS preprocessors
  • How to set up and use some of the most popular CSS preprocessors
  • What are the main features and differences of each preprocessor
  • How to write better and cleaner CSS code with preprocessors

Why use CSS preprocessors?

CSS is a simple and elegant language for styling web pages, but it also has some limitations and challenges. For example, CSS does not support:

  • Variables: You cannot store and reuse values, such as colors, fonts, or sizes, in CSS. You have to repeat them throughout your code, which makes it hard to update and maintain.
  • Nesting: You cannot nest selectors inside each other, which makes it hard to organize and structure your code. You have to write long and complex selectors, which can affect performance and specificity.
  • Functions: You cannot perform calculations, manipulate colors, or create custom logic in CSS. You have to rely on external tools or hard-code values, which can be tedious and error-prone.
  • Modularity: You cannot split your code into multiple files and import them into a single file. You have to use multiple <link> tags in your HTML, which can affect loading time and order.

CSS preprocessors solve these problems by providing advanced features that make CSS more dynamic, flexible, and modular. Some of the benefits of using CSS preprocessors are:

  • You can use variables, functions, loops, and other programming features to create dynamic and modular style sheets.
  • You can use nesting, inheritance, and operators to write more concise and readable code.
  • You can use mixins, partials, and imports to write reusable and organized code.
  • You can use built-in functions and libraries to access advanced CSS features, such as color manipulation, math operations, or grid systems.

Some of the drawbacks of using CSS preprocessors are:

  • You need to install and configure a preprocessor and a compiler, which adds some complexity to your workflow.
  • You need to learn a new syntax and follow the rules and conventions of the preprocessor you are using.
  • You need to use source maps and debugging tools to troubleshoot your code, as the compiled CSS may not match the original code.

How to set up and use CSS preprocessors?

To use a CSS preprocessor, you need to choose one that suits your needs and preferences, and then set up a development environment that supports it. You can use online tools, such as CodePen or JSFiddle, to try out different preprocessors and see how they work. You can also use local tools, such as Prepros, to compile your code and watch for changes.

The basic workflow of using a CSS preprocessor is:

  1. Write your code in the preprocessor's syntax and save it in a file with the appropriate extension, such as .scss, .less, or .styl.
  2. Run the compiler to convert your code into plain CSS and save it in a file with the .css extension.
  3. Link the CSS file to your HTML document using the <link> tag.

What are the main features and differences of each preprocessor?

There are many CSS preprocessors to choose from, but some of the most popular ones are Sass, Less, and Stylus. They all have similar features and goals, but they also have some differences in syntax, functionality, and community. Here is a brief overview of each preprocessor:

Sass

Sass is one of the oldest and most widely used CSS preprocessors. It was created in 2006 by Hampton Catlin and later developed by Natalie Weizenbaum and Chris Eppstein. Sass stands for Syntactically Awesome Style Sheets and has two syntaxes: SCSS and Sass.

SCSS is the main syntax of Sass and uses curly braces and semicolons, like CSS. It is fully compatible with CSS, which means you can write plain CSS in SCSS files. Here is an example of SCSS syntax:

CSS
                        
$primary-color: #f0f0f0;

.container {
  width: 80%;
  margin: 0 auto;
  background-color: $primary-color;
}

Sass is the older syntax of Sass and uses indentation and newlines, like Python. It is not compatible with CSS, which means you cannot write plain CSS in Sass files. Here is an example of Sass syntax:

CSS
                        
$primary-color: #f0f0f0

.container
  width: 80%
  margin: 0 auto
  background-color: $primary-color

Sass has many features, such as:

  • Variables: You can declare and use variables with the $ sign, such as $primary-color: #f0f0f0;.
  • Nesting: You can nest selectors inside each other, such as .container { h1 { color: red; } }.
  • Partials and imports: You can split your code into multiple files and import them into a single file with the @import directive, such as @import "partials/_reset.scss";.
  • Mixins: You can define and use reusable blocks of code with the @mixin and @include directives, such as @mixin rounded($radius) { border-radius: $radius; } and @include rounded(10px);.
  • Functions: You can define and use custom functions with the @function and @return directives, such as @function sum($a, $b) { @return $a + $b; } and width: sum(10px, 20px);.
  • Operators: You can perform arithmetic, relational, and logical operations, such as width: 100% / 3;, color: if($light, white, black);, and margin: 10px + 5px;.
  • Inheritance: You can extend the properties of another selector with the @extend directive, such as .error { @extend .message; color: red; }.
  • Control directives: You can use conditional and looping statements, such as @if, @else, @for, @each, and @while.
  • Built-in modules: You can use built-in modules to access various functions and features, such as @use "sass:color";, @use "sass:math";, and @use "sass:list";.

Sass has a large and active community, which means you can find many resources, tutorials, and libraries to help you learn and use it. Some of the popular Sass libraries are:

  • Compass: A framework that provides mixins, functions, and utilities for common CSS tasks, such as layout, typography, sprites, and transitions.
  • Bourbon: A library that provides mixins, functions, and helpers for modern CSS features, such as flexbox, grid, animation, and transform.
  • Susy: A toolkit that helps you create responsive layouts and grids with custom settings and options.

Less

Less is another popular CSS preprocessor that was created in 2009 by Alexis Sellier. Less stands for Leaner Style Sheets and has a syntax that is similar to CSS, but with some extensions. Less uses curly braces and semicolons, like CSS, and is fully compatible with CSS, which means you can write plain CSS in Less files. Here is an example of Less syntax:

CSS
                        
@primary-color: #f0f0f0;

.container {
  width: 80%;
  margin: 0 auto;
  background-color: @primary-color;
}

Less has many features, such as:

  • Variables: You can declare and use variables with the @ sign, such as @primary-color: #f0f0f0;.
  • Nesting: You can nest selectors inside each other, such as .container { h1 { color: red; } }.
  • Imports: You can import other files into a single file with the @import directive, such as @import "reset.css";.
  • Mixins: You can define and use reusable blocks of code with the same syntax as selectors, such as .rounded(@radius) { border-radius: @radius; } and .button { .rounded(10px); }.
  • Functions: You can use built-in functions or define custom functions with the @plugin directive, such as color: lighten(red, 10%); and @plugin "my-functions";.
  • Operators: You can perform arithmetic, relational, and logical operations, such as width: 100% / 3;, color: if(lightness(@color) > 50%, white, black);, and margin: 10px + 5px;.
  • Namespaces: You can group variables and mixins into namespaces with the # sign, such as #colors { @primary: blue; @secondary: green; } and color: #colors[primary];.
  • Scope: You can access variables and mixins from the current or parent scope, but not from the child scope, such as .parent { @color: red; .child { color: @color; // works } } and .parent { .child { @color: red; } color: @color; // does not work }.
  • Lazy evaluation: You can use variables and mixins before they are declared, as long as they are in the same scope, such as color: @color; @color: blue;.
  • Guards: You can use conditional statements to control when a mixin or a selector is applied, such as .mixin (@a) when (@a > 10) { color: red; } and .selector (@a) when (@a < 10) { color: green; }.
  • Loops: You can use recursive mixins to create loops, such as .loop (@i) when (@i > 0) { .item-@{i} { width: @i * 10px; } .loop(@i - 1); } .loop(5);.

Less has a moderate and stable community, which means you can find some resources, tutorials, and libraries to help you learn and use it. Some of the popular Less libraries are:

  • Preboot: A collection of mixins and variables for common CSS tasks, such as typography, layout, grid, animation, and transition.
  • Less Elements: A set of mixins for cross-browser compatibility and CSS3 features, such as border-radius, box-shadow, linear-gradient, and transform.
  • Less Hat: A library that provides mixins, functions, and helpers for modern CSS features, such as flexbox, grid, animation, and filter.

Stylus

Stylus is a relatively new and flexible CSS preprocessor that was created in 2010 by TJ Holowaychuk. Stylus has a syntax that is very customizable and expressive, allowing you to write code in different ways. Stylus does not use any special characters, such as curly braces, semicolons, or colons, unless you want to. It is not compatible with CSS, which means you cannot write plain CSS in Stylus files. Here is an example of Stylus syntax:

CSS
                        
primary-color = #f0f0f0

.container
  width 80%
  margin 0 auto
  background-color primary-color

Stylus has many features, such as:

  • Variables: You can declare and use variables with or without the = sign, such as primary-color = #f0f0f0 or primary-color #f0f0f0.
  • Nesting: You can nest selectors inside each other, such as .container { h1 { color: red; } }.
  • Imports: You can import other files into a single file with the @import directive, such as @import "reset.css".
  • Mixins: You can define and use reusable blocks of code with or without parentheses, such as rounded($radius) { border-radius: $radius; } and .button { rounded(10px); }.
  • Functions: You can use built-in functions or define custom functions with the @function directive, such as color: lighten(red, 10%); and @function sum($a, $b) { return $a + $b; }.
  • Operators: You can perform arithmetic, relational, and logical operations, such as width: 100% / 3;, color: if lightness(color) > 50%, white, black;, and margin: 10px + 5px;.
  • Interpolation: You can insert variables or expressions into selectors, properties, or values with the {} sign, such as .item-{i} { width: i * 10px; }.
  • Inheritance: You can extend the properties of another selector with the @extend directive, such as .error { @extend .message; color: red; }.
  • Control directives: You can use conditional and looping statements, such as if, else, for, each, and while.
  • Built-in libraries: You can use built-in libraries to access various functions and features, such as @import "nib" and @import "rupture".

Stylus has a small and growing community, which means you can find some resources, tutorials, and libraries to help you learn and use it. Some of the popular Stylus libraries are:

  • Nib: A library that provides mixins, functions, and helpers for cross-browser compatibility and CSS3 features, such as border-radius, box-shadow, linear-gradient, and transform.
  • Rupture: A library that helps you create responsive layouts and media queries with custom settings and options.
  • Axis: A framework that provides mixins, functions, and utilities for common CSS tasks, such as typography, layout, grid, animation, and transition.

How to write better and cleaner CSS code with preprocessors?

CSS preprocessors can help you write better and cleaner CSS code, but they also require some discipline and best practices to avoid common pitfalls and mistakes. Here are some tips and recommendations for using CSS preprocessors effectively:

  • Choose a preprocessor that suits your needs and preferences, and stick to it. Don't mix different preprocessors in the same project, as it can cause confusion and inconsistency.
  • Use a consistent and clear naming convention for your variables, mixins, functions, and selectors. Avoid using too generic or too specific names, and use hyphens or underscores to separate words, such as $primary-color or $primary_color.
  • Use variables wisely and sparingly. Don't use variables for every value, and don't use too many variables in the same scope. Use variables for values that are likely to change or be reused, such as colors, fonts, sizes, or breakpoints.
  • Use nesting moderately and carefully. Don't nest too deeply or too broadly, as it can affect performance and specificity. Use nesting for elements that are logically related or dependent, such as .container { h1 { color: red; } }.
  • Use mixins and functions for reusable and dynamic code. Don't use mixins and functions for simple or static code, and don't use too many arguments or parameters. Use mixins and functions for code that needs to be applied to multiple elements or customized with different values, such as .rounded($radius) { border-radius: $radius; }.
  • Use inheritance and extension for shared and common code. Don't use inheritance and extension for unrelated or unique code, and don't use too many selectors or placeholders. Use inheritance and extension for code that needs to be inherited or extended by other selectors, such as .error { @extend .message; color: red; }.
  • Use control directives and operators for complex and conditional code. Don't use control directives and operators for simple or straightforward code, and don't use too many conditions or loops. Use control directives and operators for code that needs to be executed based on certain conditions or iterations, such as @if width (body) > 500px { background color: blue; } else { background color: white; }.
  • Use imports and partials for modular and organized code. Don't use imports and partials for single or standalone code, and don't use too many files or dependencies. Use imports and partials for code that needs to be split into multiple files and imported into a single file, such as @import "partials/_reset.scss";.
  • Use libraries and frameworks for advanced and convenient code. Don't use libraries and frameworks for basic or unnecessary code, and don't use too many libraries or frameworks. Use libraries and frameworks for code that needs to access advanced CSS features or common CSS tasks, such as @import "nib";.
  • Use comments and documentation for explanatory and informative code. Don't use comments and documentation for obvious or redundant code, and don't use too many comments or documentation. Use comments and documentation for code that needs to be explained or documented for yourself or others, such as // This mixin creates a rounded border.

We hope this article gave you a better understanding of the concept and usage of CSS preprocessors.