Get in touch
Featured image for Looping with SCSS

Looping with SCSS

Posted on 15th November 2017 at 12:00pm by Chris Snowden in Code, Tutorials, Web

SCSS improves on CSS in almost every way, with nesting and powerful directives raising the stakes for front-end dev work. Sadly though, some powerful features of the language are still relatively unknown.

Loops are an excellent example of a neglected function. They can be very powerful for doing what scripting languages do best - abstracting out repetitive activities so that we don't have to!

We'll show you an example of how you might make your life easier by using an SCSS loop to create a colour scheme setup. No need for Javascript or for multiple templates and we can avoid writing out loads of selectors and keep our code DRY by using a loop to create dynamic style declarations via a master stylesheet. 

What's the plan?

We want to create a master stylesheet composed from a range of style options and duplicate this to include a range of colour variants. We will keep the styles namespaced under a control class - the page can then be switched to an alternate colour scheme by simply changing this control class.


Syntax:

We're going to need to use a few different SCSS functions for these tasks. We'll take you through them briefly now, but if you get stuck, try reading up on the syntax from the documentation links below.
note: we'll be using SCSS syntax specifically for this article as opposed to indented SASS syntax.

Interpolation:

  • To use variables in concatenation or in an expression, you'll need to use interpolation (similar to ES6 template literals or PHP interpolation) by wrapping the variable with #{}:

colour-#{$colour} 

div:nth-child(#{$i}+1);

random():

  • Returns a random number between 1-100 or a user-defined upper limit:

$randomPercent: random()+%

  • Get negative numbers like so:

$negative10: random(20) - 10;

@for and @each:

  • @for loops through a specified number of iterations. Basically, Javascript's for.
@for $i from 1 through 10 {
  $squared: $i * $i;
}
  • @each will iterate over an array or list. Basically, Javascript's forEach.
@each $name in $names {
  $index: index($names, $name);
  $loopName: $name;
}


Tip: add a @debug or @warn call to check your output is what you expect it to be:
@debug "colour set to: #{$colour}";


Instructions:

1. First, we need to specify our colours:

We are using two SCSS lists for this. An array or map could be used also. Make sure that your hex code and colour names are in the correct order and that they are not comma separated.

2. The next step is to start building our loop:

As we are looping through over an object rather than through an arbitrary number of iterations, we're going to be using an @each loop.

$colours-list is the object that we are going to loop through, and we will declare a scope $colour for each iteration. The first line of the example above sets this up using the format:

'@each item in object'

3. Now we get our iteration values: 

We need to ensure that we are grabbing the correct colour for each run through of the loop. The $colour variable is easy because we are looping through our colour list, and so the index colour is grabbed automatically, but for our $colour-name variable however, we need an extra step.

We are not looping through the colour-names list, so how will our loop know which name to grab? The answer is that we need to pass it the index of the current loop iteration. 

Get $i by using the index function to calculate the position of an item within a list. We can then use this index value to grab from the colour-names list the value which is in position $i.

e.g.

'index(list, item),

 nth(list, index)'

So for us... 
'$i: index($colours-list, $clr)'

'$colour-name: nth($colours-names, index)'

4. At this point, we should have declared both of the variables we need within the loop:

  • $colour and $colour-name.

5. The next step will be to namespace our styles: 

We want to add a control class-name, perhaps to the body tag or in our case, a panel. This is given the $colour-name variable by appending the value via interpolation. i.e: body.red, body.pink, panel-blue, panel-green.

i.e. 'class-#{value}'

6. We can now start adding our styles as normal:

Using the $colour variable, we want to write rules for the areas which we want to be dynamic - so for us...

.panel-#{$colour-name} {     

    p {       

        color: $colour;    

    }   

}

Final Code:

$colours-list: #4BA04C #6B4BA0 #A04B4B #D5C215 #0C7D72;
$colours-names: "leaf-green" "magenta" "pale-red" "solar" "aqua";

@each $clr in $colours-list {
  $i: index($colours-list, $clr);
  $colour: $clr;
  $colour-name: nth($colours-names, $i);

  .panel-#{$colour-name} {
    p {
      color: $colour;
    }
  }
}



Done! 

Hopefully that all made sense, but grab our attention if not and we'll be happy to help. Using SCSS loops can open the door to some really interesting set-ups so we'd love to hear what you come up with!


Further Reading:

Syntax:

Debugging:

Useful website for playing around with SCSS compiling if you're not set up with a build tool:



We love what we do! You will too. Speak to us