Obinna Ekwuno Writer of all things Technical and inspirational , Developer & Community Advocate. In a love-love relationship with JavaScript🔥.

How to write reusable CSS with SASS

6 min read 1912

Sass is a CSS preprocessor that is becoming vital in the front-end engineers’ toolbox. Sass gained popularity because of a couple of CSS pitfalls that it fixes.

It is also what Bootstrap 4 runs on. Meaning it would be really helpful to learn Sass in order to understand how to manipulate bootstrap code, rather than overriding the code (which is the custom method by most developers). Understanding Sass gives a better understanding of tools that are on a source code level.

When working with CSS, we are often working in a world of globals and can mistakenly style an element.

Custom CSS (even with CSS variables) is still very redundant. CSS was not designed for the kind of complex architecture we have today and we run into the problem of importing a style sheet inside another style sheet which may lead to a very large style base that may not be understood without proper documentation.

TL; DR

In this article, we will be focusing on why preprocessors are important with a particular emphasis on SASS and its ability to compose rules together. Using Sass gives a more logical approach to styling modern web components.

We will also look at why we use these preprocessors with demo examples showing how we break styling up into smaller specific components without forcing our users to download a lot of unneeded CSS files.

Prerequisites

Before we go any further, this article assumes the following:

  • Node.js ≥v6 is installed on your machine
  • npm is installed on your machine
  • Sass is installed on your machine
  • Create-react-app is installed on your machine
  • You have a basic understanding of CSS

Getting started

Sass can be added to your project in a number of ways, you can find all of the installment options here. For the sake of this article, we will be using npm by running:

npm install -g sass

What is wrong with CSS?

When learning the fundamentals of web development, we are introduced to conventional CSS which involves working with and manipulating HTML using identifiers like Classes or IDs.

While working with CSS, we oftentimes have to beat the styling to get it to look the way we want it to. It is really stressful to organize large style sheets. And keeping the classes scoped to avoid styling things in an unintended way is almost tiring.

Even with the introduction of a CSS variable to reduce the repetition with declarations, there are a few issues with this concept that are solved with using a preprocessor. Such as having long variable names.

Even with the advent of CSS3, we still need to rely on techniques (that are basically hacks) to styling user interfaces. We can also notice that while writing HTML, there is a clear nested and visual hierarchy, which regular CSS doesn’t allow for.

Let’s look at the “solution” to the features missing in CSS.

What are CSS preprocessors?

These can basically be thought of as a program that lets you generate CSS from the preprocessor’s own unique syntax. CSS preprocessors generally add some features that don’t exist in pure CSS, such as mixin, nesting selector, inheritance selector. While also giving us a very structured way of writing style sheets. Examples of CSS preprocessors include LESS, stylus, Sass, PostCSS. As stated earlier, this article is focused on Sass as a preprocessor.

csspreprocessors

SASS or SCSS?

Now if you’re new to this concept of Sass you may wonder, ‘if Sass is the preprocessor, what is SCSS’? Well , because there is a bit of confusion in using Sass because of the lack of the semicolon ; and curly brackets {} , in place of that, it uses tabs and spaces.

In version 3 of Sass, the SCSS syntax was introduced as the main syntax for Sass, it contains all the features of CSS but allows for the use of the features of Sass. Either syntax works when styling and neither one is better than the other in my opinion. The need for SCSS was to make the learning curve and implementation of Sass faster and without errors.

Sass:

$font-stack:    Helvetica, sans-serif
$primary-color: #333

body
  font: 100% $font-stack
  color: $primary-color

SCSS:

$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}

In the above code example, we notice the difference in Sass and SCSS writing styles. Note that they both use $ to declare a variable.

Concepts in SCSS

Nesting and scoping

When styling HTML files, SCSS enables you to have the same visual hierarchy of your HTML in your style sheet so you can actually map out your styling in a more understandable manner. For example, styling this index.html:

<nav class = 'sidebar'>
  <ul>
    <li> <a> </a></li>
  </ul>
</nav>

CSS:

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav li {
  display: inline-block;
}
nav a {
  display: block;
  padding: 6px 12px;
  text-decoration: none;
}

SCSS:

nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}

We can see from the CSS code example above that we are able to deduce the structure of the HTML file while keeping the implementation short and simple. Another advantage of this is that it helps to avoid spelling errors plus you can see that we have scoped some rules so that they only apply within the nav.

Descendant style rules apply in SCSS for example:

.container{
.left-area{
  ...
}
}

What this means is that all the descendants of the container class which have the class = "left-area" would be affected by the rules. Basic CSS selectors still apply to SCSS such as:

Direct descendant (>)

.container{
  > .left-area{
   ...
 }
}

Now only classes that are immediate children of the container div will get the style.

Parent selector ( & )

If we wanted to modify a class by adding a class to it, we could make use of the parent selector, it is mostly used in situations where adding a secondary style changes the style of the element. Which would also play the role of modifiers.

.container{
  & .right-area{
   background-color : #0000
 }
}

We can also use the parent selector to scope roles to another class like this:

button{
  color:#349;
  .theme-dark &{
    color: #fff
}
}

From the code example, the color #fff only applies to the .theme-dark class because of the parent selector.

Variables

Usually, in CSS, we have various style sheets linked by using @import to bring in another style sheet into the main CSS. What does this mean for the user? This would mean having to download extra CSS files.

What if there was a way to resolve all these inputs into a single CSS file using SCSS. The concept of variables in CSS comes from a JavaScript approach.

Note that @import in SCSS are used to get partials into other SCSS files but they do not become CSS files. They are denoted by having _ before the name.

Using SCSS variables

Global variables: As the name suggests, these are variables that can be accessed within a block of CSS. If you are familiar with scoping in JavaScript, you would understand global variables.

Variables in SCSS always begin with a dollar sign $.

$color: #f002
.color{
  $text_color: #ddd;
  background-color: $color;
  color: $text_color;
  text-shadow:0 0 2px darken($text_color, 40%);
}

From the code above, we notice that the $text_color can only be accessed within the block of code.

Mixins

Another awesome feature of SCSS is its ability to package reusable styling together and allow for import into another style block on demand to reduce redundancy in code.

Declaration

Creating a mixin is as simple as adding a @mixin followed by the mixin name before the block of styles, like this:

@mixin {insert name} {
     //write CSS code here
}

Usage

To use Mixins within code blocks we have to use the @include followed by the name of the mixin then a semicolon. This helps to use a predefined mixin within a code block:

.nav {
   @include {mixin name}
}

Another way of using mixins is by using arguments, like a function in JavaScript we can declare a global variable and set it as a parameter for a mixin:

@mixin text-color($color){
  background-color: $color;
  color: white;
}

//import 
.name{
  @include text-color(orange);
}
.background{
  @include text-color(white)
}

Now imagine if we wanted a default value for a mixin and would change or reassign this value in different code blocks, we would use some arguments. To show this, I will refactor the previous code example:

@mixin text-color($color : #fff){
  background-color: $color;
  color: white;
}

//import 
.name{
  @include text-color(orange);
}
.background{
  @include text-color($color: white)
}

What this does is, it sets a default color for the mixin as a base, but it is modifiable by reassigning. We could also set the value to null in order to only use the argument we need in the mixin:

@mixin text-color($color : null){
  background-color: $color;
  color: #038;
}

//import 
.name{
  @include text-color();
}
.background{
  @include text-color(#fff)
}

What this does is it makes the values that are displayed as null to have no value in the @include importation, but displays the other value by default.

Passing a deceleration block:

@mixin text-color($color){
  color: $color;
  .extra{
  @content
  }
}

//import 
.name{
  @include text-color(#fff){
    color: blue;
  }
}

The code block basically allows us to be able to keep the styling simple by styling the parent class and also being able to define the inner class.

Noteworthy info

  • Mixins do not evaluate to a CSS file, they are designed to be consumed, so you would mostly see them as partials in SCSS
  • Mixins do not need to be preceded with a dot (.)

Functions

Functions in SCSS are a big part of the features of SASS, they allow you to define complex operations that are re-usable throughout your style sheet. There are a lot of inbuilt Sass functions that can help. Check out the documentation for more information.

Here is a list of some of the functions you should be familiar with

We can also write our own Sass functions:

$width: 4px;
@function double($x){
  @return 2 * $x;
}
.thin-border{
  border-width: $width
}
.thick-border{
  broder-width:double($width)
}

The function above just doubles the value when the function is called with the normal width as a parameter.

Conditional styling with control flow

This feature is brilliant as it allows us to alternate a specific style, based on the value of another style using the @if and @else declarations. For instance, dynamically increasing a line-height for different values of font-size.

@mixin modify($size){
 font-size: $size;
 @if $size > 18{
 line-height: $size;
 }
}

//import 
.name{
 @include modify(24px)
 }

Some other features to note

  • Comments – Multiple line comments in SCSS are displayed the same way in CSS but inline comments are removed. They can be used for string interpolation (knowing what values are actually displayed in CSS)
  • Sass also comes with @for for iteration and control flow this can be used with mixins and functions

Conclusion

In this article, we have attempted to understand the basics of writing functional CSS with SCSS and also looked at some Sass/SCSS principles in general. I hope we put these practices into play towards writing more stress-free and optimized styling for our applications. Happy coding! 😄

Plug: , a DVR for web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Obinna Ekwuno Writer of all things Technical and inspirational , Developer & Community Advocate. In a love-love relationship with JavaScript🔥.

Leave a Reply