The Cascading Style Sheets (CSS) specification has been essential to website aesthetics since the mid-1990s. It’s not quite a programming language and has historically lacked most modern development tools such as functions or variables. Fortunately, SCSS provides an extension to CSS syntax that allows for such programming.
SCSS allows developers to define a variable that gets replaced at compile-time much like how #define
directives work in languages like C. When the SCSS files are compiled down to CSS each instance of a variable is replaced with its value. This makes the life of web developers easier but can cause some headaches when mixing with some native CSS features like functions.
TL;DR – use the #{}
syntax as such: calc(100vh - #{$variable});
SCSS Variables & CSS Functions
An issue can arise when using such variables in SCSS with calc
, transform
, scale
, or any number of the available CSS built-in functions. CSS functions expect a certain syntax and the $
-adorned SCSS is not within spec. Below is an example of an attempt at using an SCSS variable with the CSS calc
function that one might make without being aware of the issue:
// Define a variable $header_height: 90px; // Attempt to use it in the CSS calc function // NOTE: Does Not Work!!! .overlay{ height: calc(100vh - $header_height); }
The error message here will vary depending on how one chooses to compile their SCSS. It might be a compile-time error or simply a Unexpected term
nag via one’s linter. In any case, the issue arises from inserting the $header_height
variable directly into the CSS function.
SCSS is an extension of CSS meaning any valid CSS is also valid CSS but not all SCSS is valid CSS and such variable definition is an illustration of just that.
Immediately, this seems like a major issue. Fortunately, the work-around is simple and should feel native to any web programmer familiar with syntaxes used by React/JSX or similar tools. Below is how to insert an SCSS variable into the CSS calc function:
// Define the variable the same way $header_height: 90px; // Use the #{} syntax to insert a variable // into the calc function correctly. .overlay{ height: calc(100vh - #{$header_height}); }
This code compiles without error and will return a value of 100vh - 90px
to the height
parameter of the .overlay
class. CSS now allows programmers to use variables (a.k.a. custom properties) in a similar fashion. Consider the above code rewritten in pure CSS:
/** Defines a class to hold custom properties **/ .custom{ /** Defines the Height **/ --height: 90px; } .overlay{ /** Uses var() function to access custom property **/ height: calc(100vh - var(--height)); }
The end result in this short contrived example is the same as the previous code. The SCSS syntax is arguably sassier (living up to the directive’s name) but does lose some of the advantages of CSS custom properties. Namely, JavaScript code is not able to directly access and manipulate them since they are replaced with their static values at compile time. Additionally, CSS custom properties cascade and provide systems of inheritance.
Knowing the Difference: CSS/SASS/SCSS
Cascading Styles Sheets (CSS) is the language in which websites express their aesthetics, structure, and often much of their functionality. Syntactically Awesome Style Sheets (SASS) is a preprocessor directive by which more dynamic CSS can be written. Sassy CSS (SCSS) is the syntax in which this language is written.
SASS files are written with the extension .sass
and pre-date the SCSS files with the extension .scss
. The difference is in syntax — SCSS is an extension of CSS such that all CSS is valid SCSS whereas SASS has an indentation-formatted styling that, among other things, avoids the need for brackets. They both compile to CSS under the hood and the difference is mostly syntactic.
Final Thoughts
SCSS is utilized by most modern web frameworks that are CSS heavy like Boostrap. It greatly reduces the amount of code needed to produce comprehensive classes of style definitions for any size web project. SCSS works in complement with modern tools like webpack and typescript to help reduce the complexity of many web project code bases.
The use of SCSS variables certainly makes like easy in many cases. A little syntactic know-how can help make use of both SCSS variables and CSS functions. However, it would be a shame to write off CSS custom properties entirely given their unique ability to be directly accessed, manipulated, and inherited within the browser after compile time.