2

I'm trying to loop through a list which automates several functions. Unfortunately the function is not evaluated.

For example:

$colors:
    red,
    blue,
    green;

@each $color in $colors{
    .color-#{$color} {
        value: $color(#F15258);
    }
}

(I've simplified my example code to make it easier to illustrate).

Unfortunately this just outputs the value of $key and the color #F15258.

ie:

value: red #F15258;

Can I get SASS to pass in the variable as the function name so it actually evaluates `red(#F15258)?

It should output:

value: 241;

Any thoughts?

Prix
  • 19,417
  • 15
  • 73
  • 132
limitlessloop
  • 1,454
  • 3
  • 14
  • 21
  • Do you have a better example of what you're trying to do? There may be a solution, but it cannot be solved this way at this point in time. – cimmanon Aug 09 '13 at 13:57
  • I'm trying to loop through a list and so I don't have to perform the same set of values for each colour channel separately. Here's an example of the code I'm trying to reduce. http://codepen.io/sevenupcan/pen/iHkby – limitlessloop Aug 12 '13 at 10:11
  • If I were writing the code, it would just use a second function instead of a loop: http://codepen.io/cimmanon/pen/tyqdK. A loop isn't very efficient in this instance because you only have one truly common block of code. The function called at the beginning (red, blue, green) and the adjustment made at the end diminishes code reuse. – cimmanon Aug 12 '13 at 14:03
  • Thanks, this looks better, although I think it needs another function, because the channel var is divided by 255, but it needs to me the colour value of the channel divided by 255. – limitlessloop Aug 14 '13 at 08:49
  • @johnslegers Since your edit got rejected, just submit as another answer. – JasonMArcher Mar 30 '14 at 00:58

3 Answers3

2

As of Sass 3.3 you can do this using the call() function:

$colors:
    'red',
    'blue',
    'green';

@each $color in $colors{
    .color-#{$color} {
        value: call($color, #F15258);
    }
}

Output:

.color-red {
  value: 241;
}

.color-blue {
  value: 88;
}

.color-green {
  value: 82;
}

Note that your variables must be a string: red is a Color while 'red' is a String.

cimmanon
  • 67,211
  • 17
  • 165
  • 171
1

SASS does not allow dynamic names, and that's a good thing.

To use a dynamic name, you'll have to use a template to generate your SASS prior to compiling it. See how Compass does it: https://stackoverflow.com/a/16129685/901944

This increases the complexity of your project greatly and i strongly advise against.

Instead, use a function that accepts the name as a parameter:

@function parse-color($color) {
   // Do whatever you want here
}

.color-red {
  color: parse-color(red);
}

Note that instead of hardcoding the second color you can have it as an argument with a default value:

@function parse-color($first-color,
                      $second-color: #F15258) {
  // Do whatever you want here
  // For example:
  @return mix($first-color, $second-color);
}

$colors:
    red,
    blue,
    green;

@each $color in $colors{
    .color-#{$color} {
        color: parse-color($color);
    }
}

See a demo: http://sassbin.com/gist/6193779/

Community
  • 1
  • 1
Andrey Mikhaylov - lolmaus
  • 23,107
  • 6
  • 84
  • 133
  • Hi, thanks. Unfortunately this won't work for me because the whole point of what I'm trying to do is to reduce the code to be more maintainable, and to do that I need to use a different function for each loop. I've added an example if you are interested. http://codepen.io/sevenupcan/pen/iHkby – limitlessloop Aug 12 '13 at 10:13
  • Wow, that's some hard-to-maintain code! What task are you trying to solve in the first place? – Andrey Mikhaylov - lolmaus Aug 12 '13 at 14:15
  • Haha. I'm creating a function which will tell you the contrast ratio of two colours. I've already created it, but it's a bit unwieldy. – limitlessloop Aug 14 '13 at 09:40
  • So why don't you agree using `contrast-ratio($color1, $color2)` instead of a bunch of functions like `red-contrast-ratio($color2)`? – Andrey Mikhaylov - lolmaus Aug 14 '13 at 18:04
  • I'm not sure I understand. What I have at the moment is just one function that accepts two arguments. It's just that for each channel I have to test against a number of things which is the same for each channel, expect the function that gets the corresponding rgb value of the colour in question which requires a different function for each channel. ie `red()`, `blue()` and `green()`. – limitlessloop Aug 15 '13 at 13:24
  • Can you please share that original function? – Andrey Mikhaylov - lolmaus Aug 15 '13 at 20:00
-2

The variable with multiple values are called as lists in sass. so, you can make a list like:-

$colors: red blue green; //list of colors
@each $color in $colors{
    .color-#{$color} {
        color: ($color);
    }
}
JA9
  • 1,708
  • 3
  • 14
  • 18
  • The OP does not want to display the colors red, blue, and green, they want to run the *functions* red, blue, and green over a specific color. Totally not the same thing. – cimmanon May 27 '15 at 18:16