A Beginner's Guide to SCSS

A Beginner's Guide to SCSS

refresh basics of SCSS...

Web Notes / Tutorials

2019.11.07

0 👣 #css #scss #sass

Basically, SCSS is the most popular CSS pre-processor now people use. It’s just a more recent version of the original Sass syntax. All Sass/SCSS code compiles back to standard CSS so that the browsers can understand it. All browsers currently don’t have direct support for SCSS or any other CSS pre-processor, nor does the standard CSS specification provide alternatives for similar features, not yet.

What’s Worth

  1. Nested rules: Nest your CSS properties within multiple sets of {} brackets. This makes the CSS code a bit more clean-looking and more intuitive.

  2. Variables: Standard CSS has variable definitions. But, you can do a lot more with SCSS variables: iterate them via a for-loop and generate property values dynamically. You can embed them into CSS property names themselves. It’s useful for property-name-N{...} definitions.

  3. Better operators: You can add, subtract, multiply and divide CSS values. Although in the original CSS implements this via calc(), in SCSS you don’t have to use calc() and the implementation is slightly more intuitive.

  4. Functions: SCSS lets you create CSS definitions as resusable functions.

  5. Trigonometry: Among many of the basic features(+, -, *, /), SCSS allows you to write your own functions. You can write your own sine and cosine (trigonometry) functions entirely using just the SCSS syntax just like you would in other program languages such as JavaScript. Some trigonometry knowledge will be required. But basically, think of sine and cosine as mathematical values that help us calculate the motion of circular progress bars or create animated wave effects, for instance.

  6. Code flow and control statements: You can write CSS using familiar code-flow and control statements such as for-loop, while-loops, if-else statements similar to other languages. But don’t be fooled, SCSS still results in standard CSS in the end. It only controls how property and values are generated.

  7. Mixins: Create a set of CSS properties once and reuse or “mix” together with any new definitions. In practice, you can use mixins to create separate themes for the same layout, for example.

SCSS Pre-Processor

SCSS is not dynamic. You won’t be able to generate or animate CSS properties and values in real-time. But you can generate them in a more efficient way and let standard properties pick up from there.

New Syntax?

SCSS doesn’t really add any new features to the CSS language. Just new syntax that can in many cases shorten the amount of time spent writing CSS code.

Prerequisites

CSS pre-processors add new features to the syntax of CSS language.

There’re 5 CSS pre-processors: Sass, SCSS, Less, Stylus and PostCSS. Here, mostly focus on SCSS which is similar to Sass.

  • SASS (.sass): Syntactically Awesome Style Sheets
  • SCSS (.scss): Sassy Cascading Style Sheets

Extensions .sass and .scss are similar but not the same. For command line enthusiasts out there, you can convert from .sass to .scss and back:

# convert Sass to SCSS
sass-convert style.sass style.scss

# convert SCSS to Sass
sass-convert style.scss style.sass

Sass was the first specification for Sassy CSS with file extension .sass. The development started in 2006. But later an alternative syntax was developed with extension .scss which some developers believe to be a better one.

There is currently no out-of-the-box support for Sassy CSS in any browser, regardless of which Sass syntax or extension you would use. But you can openly experiment with any of the 5 pre-processors on codepen.io. Aside from that you have to install a favourite CSS pre-processor on your web server.

Superset

Sassy CSS in any of its manifestations is a superset of the CSS language. This means, everything that works in CSS will still work in Sass or SCSS.

Variables

Sass/SCSS allows you to work with variables. They are different from CSS variables that start with double dash you’ve probably seen before (e.g. --color: #555). Instead they start with a dollar sign (e.g. $color: #555).

$number: 1;
$color: #FFF000;
$text: "Piece of string.";
$text: "Another string." !default;
$nothing: null;

You can try to overwrite a variable name. If !default is appended to the variable re-definition, and the variable already exists, it is not re-assigned again. In other words, this means that the final value of variable $text from this example will still be “Piece of string.” and the second assignment “Another string.” is ignored, because a default value already exists.

#container {
  content: $text;
}

Nested Rules

With standard CSS, nested elements are accessed via space character:

/* standard CSS */
#A {
  color: red;
}

#A #B {
  color: green;
}

#A #B #C p {
  color: blue;
}

The above code can be expressed with Sassy’s Nested Rules as follows:

/* Nested Rules */
#A {
  color: red;
  #B {
    color: green;
    #C p {
      color: blue;
    }
  }
}

Of course, in the end, it all compiles to normal CSS, it’s just another syntax.

As you can see this syntax appears cleaner and less repetitive.

This is in particular helpful for managing complex layouts. This way the alignment in which nested CSS properties are written in code closely matches the actual structure of the application layout.

The & Character

Sassy CSS adds the & (and) character directive.

Let’s take a look at how it works!

#P {
  color: black;
  a {
    font-weight: bold;
    &:hover {
      color: red;
    }
  }
}

On line 5 the & character was used to specify &:hover and converted to the name of the parent element a after compilation.

So the result of above SCSS code when it was converted to CSS is:

#P { color: black; }
#P a { font-weight: bold; }
#P a:hover { color: red; } /* & was compiled to 'a' parent */

The & character is simply converted to the name of the parent element and becomes a:hover in this case.

Mixins

A mixin is defined by the @mixin directive (or also known as mixin rule).

Let’s create our first @mixin that defines default Flex behaviour:

@mixin flexible() {
  display: flex;
  justify-content: center;
  align-items: center;
}

.centred-elements {
  @include flexible();
  border: 1px solid gray;
}

Now, every time you apply .centred-elements class to an HTML element it will turn into Flexbox. One of the key benefits of mixins is that you can use them together with other CSS properties.

Here, it was also added border: 1px solid gray; to the .centred-elements in addition to the mixin.

You can even pass arguments to a @mixin as if it was function and then assign them to CSS properties. We’ll take a look at that in the next section.

Multiple Browsers Example

Some experimental features (such as -webkit-based) or Firefox (-moz-based) only work in browsers in which they appear.

Mixins are helpful in defining browser-agnostic CSS properties in one class.

For example, if you need to rotate an element in Webkit-based browsers, as well as the other ones, you can create this mixin that takes a $degree argument:

@mixin rotate($degree) {
  -webkit-transform: rotate($degree); // Webkit-based
  -moz-transform: rotate($degree);    // Firefox
  -ms-transform: rotate($degree);     // Internet Explorer
  -o-transform: rotate($degree);      // Opera
  transform: rotate($degree);         // Standard CSS
}

Now, all we have to do is @include this mixin in the CSS class definition:

.rotate-element {
  @include rotate(45deg)
}

Arithmetic Operators

Similar to standard CSS syntax, you can add, substract, multiply and divide values. Without having to use the calc() function from the classic CSS syntax.

But there are a few non-obvious cases that might produce errors.

Addition

p {
  font-size: 10px + 2em; // *error: incompatible units
  font-size: 10px + 6px; // 16px
  font-size: 10px + 6;   // 16px
}

Just make sure that both values are provided in a matching format.

Substraction

Substraction operator works in the same exact way as addition.

div {
  height: 12% - 2%;
  margin: 4rem -1;
}

Multiplication

The star is used for multiplication. Just like with calc(a*b) in standard CSS.

p {
  width: 10px * 10px; 				 // *error
  width: 10px * 10;   				 // 100px
  width: 1px * 5 + 5px; 			 // 10px
  width: 5 * (5px + 5px); 		 // 50px
  width: 5px + (10px / 2) * 3; // 20px
}

Division

Division is a bit tricky. Because in standard CSS the division symbol is reserved for using together with some other short-hand properties. For example, font: 24/32px defines a font with size of 25px and line-height of 32px. But SCSS claims to be compatible with standard CSS.

p { font: 16px / 24px Arial, sans-serif; }

In standard CSS, the division symbol appears in short-hand font property. But it isn’t used to actually divide values. So, how does Sass handle division?

p {
  top: 16px / 24px;					// Outputs as classic CSS
  top: (16px / 24px);				// Does division (when parentheses are added)
  top: #{$var1} / #{$var2}; // Uses interpolation, outputs as CSS
  top: $var1 / $var2;				// Does division
  top: random(4) / 5;				// Does division (when paired with function)
  top: 2px / 4px + 3px;			// Does division (when part of arithmetic)
}

If you want divide two values, simply add parenthesis around the division operation. Otherwise, division will work only in combination with some of the other operators or functions.

Reminder

The remainder calculates the remainder of the division operation. In this example. let’s see how it can be used to create a zebra stripe pattern for an arbitrary set of HTML elements.

@mixin zebra() {
  @for $i from 1 through 7 {
    @if ($i % 2 == 1) {
      .stripe-#{$i} {
        background-color: black;
        color: white;
      }
    }
  }
}

* { @include zebra() }

Note: the @for and @if rules are discussed in a following section.

This demo requires at least a few HTML elements:

<div class="stripe-1">zebra</div>
<div class="stripe-2">zebra</div>
<div class="stripe-3">zebra</div>
<div class="stripe-4">zebra</div>
<div class="stripe-5">zebra</div>
<div class="stripe-6">zebra</div>
<div class="stripe-7">zebra</div>

Comparison Operators

OperatorExampleDescription
==x == yreturns true if x and y are equal
!=x != yreturns true if x and y are not equal
>x > yreturns true if x is greater than y
<x < yreturns true if x is less than y
>=x >= yreturns true if x is greater than or equal to y
<=x <= yreturns true if x is less than or equal to y

How can comparison operators be used in practice? We can try to write a @mixin that will choose padding sizing if it’s greater than the margin:

@mixin spacing($padding, $margin) {
  @if ($padding > $margin) {
    padding: $padding;
  } @else {
    padding: $margin;
  }
}

.container {
  @include spacing(10px, 20px)
}

After compiling we will arrive at this CSS:

.container { padding: 20px; }

Logical Operators

OperatorExampleDescription
andx and yreturns true if x and y are true
orx or yreturns true if x or y is true
notnot xreturns true if x is not true
@mixin button-color($height, $width) {
  @if (($height < $width) and ($width >= 35px)) {
    background-color: blue;
  } @else {
    background-color: green;
  }
}

.button {
  @include button-color(20px, 30px)
}

Creates a button color class that changes its background color based on its width.

Strings

In some cases, it is possible to add strings to valid non-quoted CSS values, as long as the added string is trailing:

p {
  font: 50px Ari + "al"; // compiles to 50px Arial
}

The following example, on the other hand, will produce a compilation error:

p {
  font: "50px" + Arial; // Error
}

You can add strings together without double quotes, as long as the string doesn’t contain spaces. For example, the following example will not compile:

p:after {
  content: "Quoted string with " + added tail.;
}

But can be fixed with:

p:after {
  content: "Quoted string with " + "added tail.";
}

And you can add multiple strings with:

p:after {
  content: "Long " + "String " + "Added";
}

Also, you can mix the string with numbers:

p:after {
  content: "Long " + 1234567 + "Added";
}

Note: content property works only with pseudo selectors :before and :after. It is recommended to avoid using content property in your CSS definitions and instead always content between HTML tags. Here, it is explained only in the context of working with strings in Sass/SCSS.

Control-Flow Statements

SCSS has functions() and @directives (also known as rules). We’ve already created a type of function when we looked at mixins. You could pass arguments to it.

A function usually has a parenthesis appended to the end of the function’s name. A directive or rule starts with an @ character.

Just like in JavaScript or other languages, SCSS lets you work with the standard set of control-flow statements.

if()

if() is a function.

The usage is rather primitive. The statement will return one of the two specified values, based on a condition:

/* using if() function */
if(true, 1px, 2px) => 1px
if(false, 1px, 2px) => 2px

@if

@if is a directive used to branch out based on a condition.

/* using @if directive */
p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 7 < 5      { border: 2px dotted; }
  @if null       { border: 3px double; }
}

This Sassy if-statement compiles to:

p { border: 1px solid; }

Also, it works with normal @else statement:

/* create a variable $type */
$type: river;

/* paint div(s) blue if variable is set to river */
div {
  @if $type == river {
    color: blue;
  }
}

/* conditional colors on paragraph */
p {
  @if $type == tree {
    color: green;
  } @else if $type == river {
    color: blue;
  } @else if $type == dirt {
    color: brown;
  }
}

Checking If Parent Exists

The AND symbol & will select the parent element, if it exists. Or, return null otherwise. Therefore, it can be used in combination with an @if directive.

In the following examples, let’s take a look at how we can create conditional CSS styles based on whether the parent element exists or not.

/* check if parent exists */
@mixin does-parent-exist {
  @if & {
    /* apply color blue to parent if it exists */
    &:hover {
      color: blue;
    } @else {
      /* parent doesn't exist, apply blue to links */
      a {
        color: blue;
      }
    }
  }
}

p {
  @include does-parent-exist();
}

If parent doesn’t exist, & evaluates to null and an alternative style will be used.

@for

The @for rule is used for repeating CSS definitions multiple times in a row.

@for $i from 1 through 5 {
  .definition-#{$i} { width: 10px * $i; }
}

Conclusion

Just paused right here, learn as it goes.

THE END
Ads by Google

林宏

Frank Lin, PhD

Hey, there! This is Frank Lin (@flinhong), one of the 1.41 billion . This 'inDev. Journal' site holds the exploration of my quirky thoughts and random adventures through life. Hope you enjoy reading and perusing my posts.

YOU MAY ALSO LIKE

Using Liquid in Jekyll - Live with Demos

Web Notes

2016.08.20

Using Liquid in Jekyll - Live with Demos

Liquid is a simple template language that Jekyll uses to process pages for your site. With Liquid you can output complex contents without additional plugins.

Practising closures in JavaScript

JavaScript Notes

2018.12.17

Practising closures in JavaScript

JavaScript is a very function-oriented language. As we know, functions are first class objects and can be easily assigned to variables, passed as arguments, returned from another function invocation, or stored into data structures. A function can access variable outside of it. But what happens when an outer variable changes? Does a function get the most recent value or the one that existed when the function was created? Also, what happens when a function invoked in another place - does it get access to the outer variables of the new place?

Setup an IKEv2 server with strongSwan

Tutorials

2020.01.09

Setup an IKEv2 server with strongSwan

IKEv2, or Internet Key Exchange v2, is a protocol that allows for direct IPSec tunnelling between two points. In IKEv2 implementations, IPSec provides encryption for the network traffic. IKEv2 is natively supported on some platforms (OS X 10.11+, iOS 9.1+, and Windows 10) with no additional applications necessary, and it handles client hiccups quite smoothly.