Writing a loop that increments by a value other than 1 in Sass
Asked Answered
W

6

52

In SASS, a loop is written like so:

@for $i from 1 through 100 {
    //stuff
}

This would yield 1, 2, 3, 4... all the way to 100.

How would you make the loop go in intervals of two units?

@for $i from 1 through 100 *step 2*{
    //stuff
}

So the result is 1, 3, 5, 7... to 99

Worrisome answered 14/9, 2013 at 13:15 Comment(0)
R
62

It isn't in the documentation because it simply isn't implemented. What you want to do can be done with the @while directive.

$i: 1;
@while $i < 100 {
  // do stuff
  $i: $i + 2;
}
Ribald answered 14/9, 2013 at 14:6 Comment(0)
C
30

Sass does not provide a way to specify how much to increment using @for loops. Instead, you write your loop to reflect how many steps you need to take to get your final output. For all of the odd numbers from 1 through 100, that's 50 steps (100 / 2). Inside the loop, you use arithmetic (addition, subtraction, multiplication, division) to arrive at your final value.

@for $i from 1 through 50 {
  $value: $i * 2 - 1;
  // stuff
}

DEMO

or a bit more general version:

$max: 100;
$step: 2;

@for $i from 1 through ceil($max/$step) {
  $value: ($i - 1)*$step + 1;
  // stuff
}

DEMO

Chubby answered 1/11, 2013 at 20:4 Comment(0)
H
22

I'd use Modulus for this. The Modulus operator gives you the remainder of the division of a number into another number. E.g (3 % 2) will give you 1, as will (5 % 2) or (7 % 2).

If you used this:

@for $i from 1 through 100 {
    @if $i % 2 == 0 {
        #{$i}
    }
}

You'll get 2,4,6,8,10...100

But you want 1,3,5,7,9...99 – so offset it by 1:

@for $i from 1 through 100 {
    @if ($i+1) % 2 == 0 {
        .your-class-#{$i} {
          // do stuff
        }
    }
}
Holifield answered 25/8, 2016 at 10:38 Comment(3)
This is my preferred method, because not only is it simple, but it doesn't involve the alteration/creation of any new variables, just to do the math. It just checks the result of a simple operation. Beautiful.Aggarwal
This is such a good way to control the range, as well as stepping through. Thanks for sharing this.January
One disadvantage to this is that you have to do (max) iterations, rather than just one for every step. So, if you do @for $i from 1 through 100 {@if $i % 50 == 0 {}} you'll run the loop 100 times to do 2 things. Given SASS is compiled ahead of time, maybe not a huge deal unless you're using it a lot.Exactly
W
1

Other example more:

.my-class {
    $step    : 5;
    $from    : ceil( 1 /$step);
    $through : ceil( 100 /$step);
    $unit    : '%';

    @for $i from $from through $through {
      $i : $i * $step;
      width: $i#{$unit};
    }
}
Wills answered 14/8, 2015 at 20:14 Comment(2)
Can you please explain why this would solve the problem?Atmo
I don't see what this adds over the existing answers.Chrissy
L
0

I think sass didn't implement this because it's quite easy to achieve. Just define a new variable in the loop block that multiplies the loop value with the step you wish to have.

General example

@for $i from 1 through 9 {
  $v: $i * 100;
  .w#{$v} {
   font-weight: $v;
}
}

Example with your code

@for $i from 1 through 100 {
    //stuff
    // multiple value by your step
    $new_value: $i * 2;
    // use $new_value here:
}
Landholder answered 23/8, 2021 at 7:5 Comment(0)
M
0

If you will be using this feature a lot, you can create your own mixin and call it like so:

@mixin range($from, $to, $step: 1) {
    $i: $from;
    @while $i < $to {
        @content($i);
        $i: $i + $step;
    }
}

div {
    @include range(80px, 120px, 10px) using($i) { // Supports units
        width: $i; // you have access to $i.
    }
}

output:

div {
  width: 80px;
  width: 90px;
  width: 100px;
  width: 110px;
}
Meade answered 24/11, 2022 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.