Sass Multiple Arguments, Lists or Arglist

Share this article

I do a lot of Sass code reviews. Along the same lines, I like to read frameworks’ code. Needless to say, I have seen a lot of things, both good and bad, when it comes to Sass.

If there is something that always make me grind my teeth when I read other people’s Sass, it’s seeing mixins and functions using lists instead of variable arguments, or using lists instead of multiple named arguments.

In this article I’d like to take a look at this issue and, hopefully, show when to use what more clearly.

Terminology

Before going any further let’s have a quick look at the terminology. Both functions and mixins are able to accept arguments, from 0 to infinity. That means you can make an argument-less function/mixin or one with a multitude of arguments. Now let’s go deeper.

In Sass, a list is the equivalent to an array in other languages. A value that happens to have list as a type (checked with the type-of function) is a collection of several values that have a specific type (number, string, bool, color, list, map or null). For a deeper understanding of Sass lists, I suggest you read my article about this.

Last but not least, there is a variable argument. You may not have known that arglist is an actual Sass data type (it’s mentioned nowhere in the docs). The thing is, you cannot easily create an arglist (deliberately) because it is usually an internal mecanism from Sass which happens when you use the variable argument notation within a mixin/function signature.

For instance:

@mixin shadows($shadows...) {
  box-shadow: $shadows;
}

In this example, $shadows is an arglist. By using ... in the signature, we make it possible to pass any number of arguments, from none to a bazillon. It shares the exact same traits with a regular list, except that it is always comma-separated since several arguments are delimited by commas.

Now that we are okay with the terminology, it’s time to determine what to use when. Let’s start with the easy one.

The variable argument

If you don’t know how many arguments will be passed to the function/mixin because there could be none or as many as the number of stars in the universe, it means you whould be dealing with an unknown number of arguments, a.k.a. an arglist.

For instance, let’s consider a linear-gradient mixin:

@mixin linear-gradient($direction, $gradients...) {
  background-color: nth($gradients, 1);
  background-image: linear-gradient($direction, $gradients...);
}

.selector {
  @include linear-gradient(to right, magenta, red, orange, yellow, green, blue, purple);
}

This is the perfect case for a variable argument because there can be any number of color-stops passed to the mixin. Don’t use a list only to loop and create a comma separated list… It makes no sense.

Multiple arguments

Now let’s move on to multiple arguments. Multiple distinct named arguments are often used when dealing with unrelated arguments. Sticking to our gradient mixin, we wouldn’t package the direction in the gradients list. It serves a completely different purpose and thus should stand in its own argument.

In most cases, you will use multiple arguments rather than a list of an arglist. It is the common use case, a function/mixin needs a, b and c to work, so you make it accept three arguments: $a, $b and $c. If some of those arguments have a default value, you add this default value within the mixin signature, for instance $a, $b, $c: "default".

One thing very few people know about, is that setting multiple arguments within a function/mixin signature doesn’t necessarily mean you have to pass them one by one. Let’s put aside our gradient mixin and consider a dummy function for a minute:

@function dummy($a, $b, $c: "default") {
  // do stuff
}

Now, let’s say you have a list called $parameters with the 3 arguments ready.

$parameters: (true, 42, 'kittens');

There are two ways for you to call the function based on your list of parameters. Either like this, which is inelegant:

$value: dummy(nth($parameters, 1), nth($parameters, 2), nth($parameters, 3));

Or like this, instructing Sass to pass $parameters as a variable argument:

$value: dummy($parameters...);

While the second version is quite handy, it requires the $parameters to be correctly ordered. To work around this, there is a third way of doing so since Sass 3.3, using a map:

$parameters: (
  'c': 'kittens',
  'a': true,
  'b': 42
);

$value: dummy($parameters...);

By making map keys matching the arguments name, you can convert a map to a variable argument on the fly by appending ... to it. Sass will correctly grab values in the correct order.

Back to our initial topic. Using multiple distinct arguments is much more powerful than requiring the user to pass a list, because you give them the choice: either they can pass arguments one by one, or all at once with either a list or a map.

So think twice next time you want to replace a couple of arguments with a list with a function/mixin signature.

The list

From what I can tell, it is quite unusual to have a mixin or function expecting a list. Either you would use multiple arguments because they are all unrelated, or you would pass an arglist because your function/mixin needs to accept any number of related arguments.

List are often used as an internal tool to store several values within a unique variable. However, some functions/mixins might expect a list because they actually do some manipulation on this list. For instance a function testing whether a value is contained within a list obviously needs a list to work. Not named arguments since we don’t know the number. Not a variable argument since it is a single entity.

@function contains(/* List */ $haystack, /* Any */ $needle) {
  @return not not index($haystack, $needle);
}

Allow me to drift a little bit. The current version of Bourbon provides a mixin to help sizing elements. The idea is simple: you pass it one value, it assigns it to both width and height you pass it two values, it gives width the first and height the second.

Now, this is easily doable with something like this:

/// Helper mixin to size elements
/// @param {Number} $width - Width
/// @param {Number} $height ($width) - Height
@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}

If $height is not defined, it should fall back to its default value which happens to be the value of $width. It’s both elegant and concise. Now, I am not quite sure why Bourbon decided to go the other way and ask for a list instead.

/// Helper mixin to size elements
/// @param {List} $size - Width and possibly height (but not mandatory)
@mixin size($size) {
  $height: nth($size, 1);
  $width: $height;

  @if length($size) > 1 {
    $height: nth($size, 2);
  }

  width: $width;
  height: $height;
}

I mean, why? In this case, it makes absolutely no sense to use a list. Both values are unrelated, so they should not be packaged within the same variable. Also, Sass comes with a built-in way to set default values directly from the signature.

The only gain from this version is not to have to type the comma when calling the mixin:

// Standard mixin
.selector {
  @include size(13px, 37px);
}

// Bourbon mixin
.selector {
  @include size(13px 37px);
}

It definitely does not seem worth it, if you ask me.

Tl;dr

If you expect an unlimited number of arguments, don’t use a list, use an arglist. This data type has been designed for such a purpose.

If you expect a limited number of arguments, don’t use a list, use multiple named arguments. This will allow you to pass them one by one or all at once using a list or a map.

If you expect a list for your mixin/function, use a list. You could use an arglist but it would’nt make much sense.

Frequently Asked Questions (FAQs) about Sass Multiple Arguments, Lists, and Arglist

What is the purpose of using multiple arguments in Sass?

Multiple arguments in Sass are used to make your code more dynamic and flexible. They allow you to pass several values into a function or mixin, which can then be used to perform various operations or generate different styles. This feature is particularly useful when you want to create complex styles that depend on several variables. By using multiple arguments, you can reduce code repetition and make your stylesheets easier to maintain and update.

How can I pass a list to a mixin with multiple arguments in Sass?

To pass a list to a mixin with multiple arguments in Sass, you can use the … (spread) operator. This operator allows you to pass each item in the list as a separate argument to the mixin. Here’s an example:

@mixin box-shadow($shadows...) {
-webkit-box-shadow: $shadows;
-moz-box-shadow: $shadows;
box-shadow: $shadows;
}

$shadows: 0px 4px 5px #666, 2px 6px 10px #999;

@include box-shadow($shadows...);

In this example, the $shadows list is passed to the box-shadow mixin as multiple arguments using the … operator.

What is the difference between lists and arglist in Sass?

In Sass, a list is a data type that can hold multiple values, similar to an array in other programming languages. An arglist, on the other hand, is a special type of list that is used to hold the arguments passed to a function or mixin. While a regular list can be used as an argument, an arglist allows you to pass an arbitrary number of arguments to a function or mixin. This makes it more flexible and powerful than a regular list.

Can I use multiple return statements in a Sass function?

No, you cannot use multiple return statements in a Sass function. A Sass function will stop executing as soon as it encounters a return statement, and the value of that statement will be the result of the function. If you need to return multiple values from a function, you can use a list or a map.

How can I use the @function rule in Sass?

The @function rule in Sass allows you to define your own functions. These functions can take arguments, perform operations, and return a value. Here’s an example:

@function calculate-width($columns) {
@return $columns / 12 * 100%;
}

.container {
width: calculate-width(6);
}

In this example, the calculate-width function takes a number of columns as an argument and returns the corresponding percentage width.

What is the @mixin rule in Sass and how is it used?

The @mixin rule in Sass allows you to define reusable chunks of CSS. These mixins can take arguments and generate different styles based on those arguments. Here’s an example:

@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}

.box {
@include border-radius(10px);
}

In this example, the border-radius mixin takes a radius as an argument and generates the corresponding CSS for different browsers.

How can I use the @content directive in a Sass mixin?

The @content directive in a Sass mixin allows you to insert custom CSS into the mixin. This can be useful when you want to create a mixin that provides a general structure, but allows for customization. Here’s an example:

@mixin media($width) {
@media (max-width: $width) {
@content;
}
}

@include media(600px) {
.container {
width: 100%;
}
}

In this example, the media mixin takes a width as an argument and generates a media query. The @content directive is used to insert the custom CSS for the .container class.

Can I use Sass functions and mixins in regular CSS?

No, Sass functions and mixins cannot be used in regular CSS. They are features of the Sass preprocessor and are not recognized by CSS. However, when you compile your Sass code, the functions and mixins will be replaced with the corresponding CSS.

How can I define default values for arguments in a Sass function or mixin?

You can define default values for arguments in a Sass function or mixin by using the = operator. Here’s an example:

@mixin border($width: 1px, $style: solid, $color: black) {
border: $width $style $color;
}

.box {
@include border($color: red);
}

In this example, the border mixin takes three arguments with default values. If you don’t provide a value for an argument when you include the mixin, the default value will be used.

Can I use Sass variables in a function or mixin?

Yes, you can use Sass variables in a function or mixin. The variables can be defined outside the function or mixin and then used inside it. However, keep in mind that if you define a variable with the same name inside the function or mixin, it will shadow the external variable.

Kitty GiraudelKitty Giraudel
View Author

Non-binary trans accessibility & diversity advocate, frontend developer, author. Real life cat. She/they.

sasssass functionssass mixinsStuR
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week