# Lists in Sass: syntax and use cases with examples

Sass lists are ordered collections of values, similar to arrays in other
languages.

Lists fit naturally into CSS because values such as `10px 15px 0 0` and
`Helvetica, Arial, sans-serif` are already lists. Sass adds functions and loops
for reading and transforming them.

## Defining a list

A space-separated list needs no brackets:

```scss
$horse-types: pony horse mini-horse maxi-pony;
```

Lists can also use commas:

```scss
$horse-types: pony, horse, mini-horse, maxi-pony;
```

Quote an item when spaces must remain part of that single value. Without the
quotes, `mini horse` would be two items:

```scss
$horse-types: 'pony', 'horse', 'mini horse', 'maxi pony';
```

Lists can be nested. Here, commas separate the outer list and spaces separate
each name-and-color pair:

```scss
$horses: (pony #996633), (horse #fff), (mini-horse #333), (maxi-pony #cc9849);
```

Parentheses group each inner list. Square brackets are also allowed, which is
useful for CSS Grid line names:

```scss
$grid-lines: [main-start] 1fr [content-start] 2fr [main-end];
```

See the Sass documentation for the full
[list syntax](https://sass-lang.com/documentation/values/lists/).

## Noteworthy things about lists

- Indexes start at `1`, not `0`. Negative indexes count back from the end.
- List functions treat a single value as a one-item list.
- Maps also count as lists of key/value pairs.
- Lists are immutable. Functions return new lists instead of changing the
  original.

For example:

```scss
@use 'sass:list';

@debug list.length('Fire Walk with Me'); // 1
@debug list.length(Fire Walk with Me); // 4
```

## List functions

Load the built-in module with `@use 'sass:list'`, then call its functions with
the `list.` namespace. The older global names such as `nth()` still exist, but
the module API makes their origin clear.

| Function                                                        | Description                                    |
| --------------------------------------------------------------- | ---------------------------------------------- |
| `list.append($list, $value, $separator: auto)`                  | Returns a copy with one value added to the end |
| `list.index($list, $value)`                                     | Returns the first matching index, or `null`    |
| `list.is-bracketed($list)`                                      | Reports whether the list uses square brackets  |
| `list.join($list1, $list2, $separator: auto, $bracketed: auto)` | Combines two lists                             |
| `list.length($list)`                                            | Returns the number of items                    |
| `list.nth($list, $n)`                                           | Returns the item at an index                   |
| `list.separator($list)`                                         | Returns `space`, `comma`, or `slash`           |
| `list.set-nth($list, $n, $value)`                               | Returns a copy with one item replaced          |
| `list.slash($elements...)`                                      | Creates a slash-separated list                 |
| `list.zip($lists...)`                                           | Combines matching positions into nested lists  |

See the
[`sass:list` reference](https://sass-lang.com/documentation/modules/list/) for
details and compatibility notes.

## Accessing a list

Use `list.nth()` to read an item:

```scss
@use 'sass:list';

$horse-types: pony horse mini-horse maxi-pony;

@debug list.nth($horse-types, 1); // pony
@debug list.nth($horse-types, -1); // maxi-pony
```

Use an [`@for` loop](https://sass-lang.com/documentation/at-rules/control/for/)
when you need the index as well as the value:

```scss
@use 'sass:list';

$horse-types: pony horse mini-horse maxi-pony;

@for $i from 1 through list.length($horse-types) {
  .horse-#{$i}::after {
    content: '#{$i}. #{list.nth($horse-types, $i)}';
  }
}
```

When you only need each value, an
[`@each` loop](https://sass-lang.com/documentation/at-rules/control/each/) is
shorter:

```scss
$horse-types: pony horse mini-horse maxi-pony;

@each $horse in $horse-types {
  .horse-photo--#{$horse} {
    background-image: url('/images/horses/#{$horse}.png');
  }
}
```

## Accessing nested lists

Consider the name-and-color pairs from earlier:

```scss
$horses: (pony #996633), (horse pink), (mini-horse #333), (maxi-pony #cc9849);
```

Each pass through the loop gives us one inner list. We can access its two items
with `list.nth()`:

```scss
@use 'sass:list';

@each $horse in $horses {
  $name: list.nth($horse, 1);
  $color: list.nth($horse, 2);

  .horse--#{$name} {
    background-color: $color;
    background-image: url('/images/horses/#{$name}.png');
  }
}
```

The two levels look like this:

```text
$horses
  │
  ├─ $horse: pony #996633
  │           │       │
  │           │       └─ list.nth($horse, 2) → #996633
  │           └───────── list.nth($horse, 1) → pony
  │
  ├─ $horse: horse pink
  ├─ $horse: mini-horse #333
  └─ $horse: maxi-pony #cc9849
```

An `@each` loop can destructure the inner lists, so this is usually simpler:

```scss
@each $name, $color in $horses {
  .horse--#{$name} {
    background-color: $color;
    background-image: url('/images/horses/#{$name}.png');
  }
}
```

## Adding to a list

Use `list.append()` to return a new list with one value added:

```scss
@use 'sass:list';

$horse-types: pony horse mini-horse maxi-pony;
$horse-types: list.append($horse-types, shetland);

@debug $horse-types; // pony horse mini-horse maxi-pony shetland
```

The reassignment matters because the original list cannot be changed. Pass
`$separator: comma`, `$separator: space`, or `$separator: slash` when the result
needs a specific separator:

```scss
$horse-types: list.append($horse-types, mustang, $separator: comma);
```

Use `list.join()` instead when combining two complete lists.

## Lists or maps?

Lists work well for ordered values, repeated variants, and arguments that map
directly to CSS:

```scss
$card-corners: 1rem 1rem 0 0;

.card {
  border-radius: $card-corners;
}
```

If each value has a name, a
[map](https://sass-lang.com/documentation/values/maps/) usually communicates the
structure better than a nested list:

```scss
$horse-colors: (
  pony: #996633,
  horse: pink,
  mini-horse: #333,
  maxi-pony: #cc9849,
);

@each $name, $color in $horse-colors {
  .horse--#{$name} {
    background-color: $color;
  }
}
```
