Skip to content

syzygypl/introduction-to-advanced-sass

Repository files navigation

Introduction to advanced Sass

by Marcin Gościcki — 28 January 2022

This is a brief description of Sass features and good practices spiced up with some explanations, examples and useful links. It doesn't cover all the aspects (like partials, nesting or operators) and requires at least basic knowledge of Sass. Learn Sass!

Demo page itself was created using described solutions and techniques so go ahead and check the code.

Go to demo page!


1. Why to use CSS preprocessors?

Click to expand!

Simply, not everything is yet possible in pure CSS. However, some things like variables (CSS Custom Properties) are available and others like CSS Nesting, or Custom Media Queries are on the way!

Unfortunately there are still many things that can't be achieved yet and soon with pure CSS:

  • built-in and custom functions, loops, mixins, extending, etc.,
  • complex variable types like objects or arrays,
  • sane code splitting into multiple files.

Further readings:

...and other implementations.

Click to expand!

Dart Sass is the only actively maintained Sass implementation. LibSass and Node Sass (which is only a wrapper for LibSass) are deprecated - they are getting only fixes to major bugs and security issues, no new features. Ruby Sass is dead.

The major new feature available only in Dart Sass is a module system. Sass Modules comes with namespaces, new at-rules (@use and @forward) and built-in modules that includes (not only) built-in functions.


Further readings:

3. Values and $variables.

Click to expand!

Even though (CSS Custom Properties) are great, they are still quite primitive. They were created to store simple value types like numbers, strings or colors. Sass extends it with booleans, null values, maps and even function references. Those are crucial for writing smart, reusable and manageable stylesheets. Variables hold Values.

It is worth mentioning that preprocessor Variables and CSS Custom Properties are much different. The first can be considered variables only before the compilation. Custom properties are "live" in browser - they can be overwritten, their value can be changed (e.g. by media query) and manipulated in JavaScript. That's why they can complement each other so well!


Further readings:

4. Flow control - @if, @each, @for and @while.

Click to expand!

Sass provides a number of at-rules that make it possible to control whether styles get emitted, or to emit them multiple times with small variations. They can also be used in mixins and functions to write small algorithms to make writing your Sass easier.


Sass: Documentation - Flow Control Rules — sass-lang.com

Nothing to add over and above what the documentation says.


Further readings:

5. @function.

Click to expand!

Functions allow you to define complex operations on SassScript values that you can re-use throughout your stylesheet. They make it easy to abstract out common formulas and behaviors in a readable way.


Sass: Documentation - @function — sass-lang.com

Functions often come in handy when you need to retrieve some Value from a Map. A good example here is z-index management. The other use cases would be repetitive Operations like generating box-shadow from given colors. You may also need to wrap some build-in function to extend its functionality.


Further readings:

6. @mixin and @include.

Click to expand!

In the past most examples of Mixin I can remember were about adding vendor prefixes. Up to early 2019 it was even in the official documentation of Sass. Now we have better alternatives for that, like Autoprefixer.

Mixins are still very useful when we have reusable blocks of styles or / and we want to assure consistency. Good examples are: elements resets, repetitive styles (like consistent borders and box shadows) or media queries.


Further readings:

7. @extend and %placeholder.

Click to expand!

NOTE: Without a quotation from the Sass documentation as they convince you to break BEM (❤️) principal rule and use modifiers alone.

Extends allow to "inherit" styles from one selector to another. Placeholders are selectors that may only be extended and don't produce any output itself. Unlike @mixin and @inlude the @extend rule produces Groups of selectors so the output is smaller. Besides, @extend generates also a handful of problems and limitations:

  • it may mess with code order, as styles are resolved in place of extended element, not where @extend is applied,
  • only simple, "individual" selectors can be extended,
  • extend can't be used inside of @media if wasn't declared in it.

With all that being said my private rule is to prefer @mixin and @include over @extend. Especially if the output CSS will be served compressed from the server so the filesize won't be substantially larger.

However, there are certain situations when choosing @extend seems right. That's when we need to pull out only some styles to a separate stylesheet or / and we need to style by HTML tags in some specific context. A good real-live example here is a separate CSS file for WYSIWYG where we have no influence on produced markup, and we can only relay on HTML tags. It seems right to extend some selectors rather than rewriting whole code to use Mixins and Icludes.


Further readings:

8. Modules - @use and @forward.

Click to expand!

The old-way in Sass was to @import files to combine them into single CSS file or to use Vars, Mixins or Functions from another SCSS files. Modules resolve drawbacks of @import, which are:

  1. Global scope: All members (vars, mixins and functions) are globally accessible and hard to trace where are defined.
  2. Naming collisions: Because of global scope that is easy to unintentionally override some members. That's why prefixes like $button-height were widely used.
  3. May be confused with native CSS @import rule.
  4. @import is slower than @use as it executes stylesheet and emits CSS on every occurrence.

@forward rule works similar to @use but allows other modules to be used directly from module where are forwarded. It's handful when you want to organize stylesheets across many files but provide single entry point - great for UI libraries!


Further readings:

9. Sass JavaScript API.

Click to expand!

The sass package on npm is a pure-JavaScript package built from the Dart Sass implementation. (...) it provides a JavaScript API that can be used to drive Sass compilations from JavaScript. It even allows an application to control how stylesheets are loaded and define custom functions.


Sass: Documentation - JavaScript API — sass-lang.com

It means that Sass may be adapted to developers needs by themselves. Do you need to customize Sass compilation? You can create JavaScript functions to be run on your Sass Values. Would you like to use SVG files directly in your stylesheets, automatically encoded to base64? Or maybe you have some data in JSON or YAML files that you could @import / @use in your Sass? Go for it! But first check if some else didn't already create the function or importer you need.

NOTE: Many importers names starts with node-sass but most will work with Dart Sass as API is compatible.


Further readings:

10. "Programming in Sass".

...everything put together.

Click to expand!

Can we call Sass a "programming language"? Depends on definition.

For sure creating complex UI libraries nowadays requires solid architecture and advanced techniques to make manageable, high quality output. All above described solutions and techniques help to write high quality code that meets DRY principle.


Further readings:


© Marcin Gościcki / SYZYGY Warsaw — 2022

About

Brief description of advanced Sass features and good practices spiced up with some explanations, examples and useful links

Topics

Resources

Stars

Watchers

Forks