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!
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:
- Learn Sass — sass-lang.com
...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:
- LibSass is Deprecated — sass-lang.com
- Announcing Dart Sass — sass-lang.com
- Introducing Sass Modules — css-tricks.com
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:
- Sass: Documentation - Values — sass-lang.com
- Sass: Documentation - Variables — sass-lang.com
- What is the difference between CSS variables and preprocessor variables? — css-tricks.com
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:
- Sass: Documentation - Flow Control Rules — sass-lang.com
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:
- Sass: Documentation - @function — sass-lang.com
- Systems for z-index — css-tricks.com
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:
- Sass: Documentation - @mixin and @include — sass-lang.com
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:
- Sass: Documentation - @extend — sass-lang.com
- Sass: Documentation - Placeholder Selectors — sass-lang.com
- Sass: Documentation - Extends or Mixins? — sass-lang.com
- Optimizing Encoding and Transfer Size of Text-Based Assets — developers.google.com
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:
- Global scope: All members (vars, mixins and functions) are globally accessible and hard to trace where are defined.
- Naming collisions:
Because of global scope that is easy to unintentionally override some members. That's why prefixes like
$button-height
were widely used. - May be confused with native CSS
@import
rule. @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:
- Sass: Documentation - @import — sass-lang.com
- Sass: Documentation - @use — sass-lang.com
- Sass: Documentation - @forward — sass-lang.com
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:
- Sass: Documentation - JavaScript API - Interface Importer — sass-lang.com
- Sass: Documentation - JavaScript API - Custom Function — sass-lang.com
...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:
- How long until @SassCSS is Turing complete? — twitter.com
- Is CSS a Programming Language? — css-tricks.com
© Marcin Gościcki / SYZYGY Warsaw — 2022