ricksmt
ricksmt

Reputation: 899

Sass: Function to map variable number of inputs

Suppose I have the following in SCSS:

$browser-context: 16;
@function em($size, $context: $browser-context) {
    @if (unitless($size)) { $size: $size * 1px; }
    @if (unitless($context)) { $context: $context * 1px; }
    @return ($size / $context) * 1em;
}

With this, I can write the following:

.test { padding: em(20px); }

Which will output the following CSS:

.test { padding: 1.25em; }

And everything is hunky dory. Is there any way that I can transform an unknown amount of inputs in one call? For example:

.text { padding: func(20px 30px); }

and

.text { padding: func(20px 30px 10px); }

would output

.text { padding: 1.25em 1.875em; }

and

.text { padding: 1.25em 1.875em 0.625em; }

respectively. I'm just hoping to avoid doing this:

.text { padding: em(20px) em(30px) em(10px); }

Upvotes: 2

Views: 70

Answers (1)

cimmanon
cimmanon

Reputation: 68349

What you're looking for is a map function (commonly found in other languages to apply a function on each item in a list), but Sass does not provide one. However, you can write your own starting with Sass 3.3 by using the call() function as you loop over the entire list.

@function map($fun, $list) {
    @for $i from 1 through length($list) {
        $list: set-nth($list, $i, call($fun, nth($list, $i)));
    }
    @return $list;
}

Usage:

$bar: 10px 20px 30px;

@function times2($i) {
    @return $i * 2;
}

.foo {
    padding: map('times2', $bar); // note the quotes around the function name
}

Output:

.foo {
  padding: 20px 40px 60px;
}

Upvotes: 2

Related Questions