Sass in the Real World: book 2 of 4

if(), @if, @else and @else if control directives

Software developer joke:

A developer, while at the grocery store, calls his wife and asks "Do we need anything from the store?" His wife replies "Yes, we need bread. And if they have eggs, get a dozen" The developer arrives home and to his wife's astonishment, he had bought a dozen loaves of bread.

In the Sass documentation, the @if directive is said that it is a SassScript expression that will use the styles nested within the argument if the expression returns anything other then false or null.

But what does that mean? The ability to evaluate boolean logic is a basics feature of every programming language. This evaluation can involve a basic boolean variable or any other variable/expression that can be evaluated to true or false.

In the following example we will use the @if control directive and a simple boolean variable to evaluate something like this:

$truthy: true !default;
$falsy: false !default;

@if $falsy {
  @deubg "I am false";
} @else if $truthy {
  @deubg "I am truth";
}

Running this code we get the following output:

@deubg "I am truth";

But why? What's interesting about this example, the value of $falsy is false, so this meets the criteria of being either false or null. As a result, the @if statement then reviews the @else if query to evaluate it's boolean value. As a result, $truthy comes back as true so Sass will print out the rules from within. @else if works in Sass much like other languages, whereas @else will simply return a rule when all other queries have failed and @else if must be evaluated and come back as true before the rules are used.

If we were to update the variables being set to the following, we would get a different response:

$truthy: null !default;
$falsy: true !default;

Resolves to:

@deubg "I am false";

And as long as we are talking about it, the @debug directive simply prints the value of a SassScript expression to the error output stream. This is a pretty useful tool when debugging Sass files that contain complicated SassScript, for example:

$val: 100;
$var: 1984;

.block {
  @debug $val != $var;
}

When processed, Sass will return:

<file name>.scss:<lione number> DEBUG: true

OR and AND operators

Using @if also allows for the use of OR or AND operators to evaluate multiple logical values. For example, in the following code, we have two variables. One with an empty list and the other with a list containing two objects. The @if statement will evaluate if the length of empty list is greater then '0 OR if the length of $test-listis greater then0`.

$empty-list: () !default;
$test-list: (test me) !default;

@if length($empty-list) > 0 or length($test-list) > 0 {
  @debug "I have a list";
} @else {
  @debug "where is my list?";
}

Conversely, using the and operator, we can evaluate if one thing AND another are true.

$empty-list: () !default;
$test-list: (test me) !default;

@if length($empty-list) > 0 and length($test-list) > 0 {
  @debug "I have a list";
} @else {
  @debug "where is my list?";
}

The if() function

Much like the @if directive, the if() function evaluates if something is true or not and then provides the appropriate return. The syntax is pretty simple, as illustrated in the following:

if(condition, true, false);

But how do we make use of this? Let's say for example we have a need to evaluate the value of a variable and make sure that it is actually a color. Using the @if directive, we could write something like the following. Pretty simple really. When using the function of color() pass in a color value or something totally off base. The function will use the built in Sass function to evaluate what type the passed in value is. If it is a color, then return the color. If it is not, return a null value.

@function color($val) {
  @if type-of($val) == color {
    @return $val;
  } @else {
    @return null;
  }
}

To use this, simply reference the function with a CSS attribute in this example. Here the function will return a null value and thus the CSS rule would not be printed out. NOTE, there is a bug in libsass where the null value will be printed out.

.block {
  color: color(foo);
}

Using the new if() function, we can actually wrap all this logic up into a single line of code. Remember the syntax?

if(condition, true, false);

Knowing this, to re-factor the previous code, just do the following:

@function color($val) {
  @return if(type-of($val) == color, $val, null);
}