# for

> Loop over arrays, hashes and other collections.

`for` renders its content once for each item in a collection. An `else` section renders when there are no items.

page.kiln:

```kiln
{% for post in posts %}
	<h2>{{ loop.index }}. {{ post.title }}</h2>
{% else %}
	<p>No posts yet.</p>
{% endfor %}
```

Output:

```html
<h2>1. Hello</h2>
<h2>2. Second post</h2>
```

`for` works with arrays, hashes, sets, maps and other iterables. Looping over null is the same as looping over an empty array. Async iterables aren't supported, because Kiln doesn't wait for them: have your function collect the items into an array.

## Keys and values

Give two names to get each key and value. For arrays, the key is the index, starting at 0.

page.kiln:

```kiln
{% for key, value in settings %}
	{{ key }}: {{ value }}
{% endfor %}
```

Output:

```html
theme: dark
lang: en
```

## The loop variable

Inside a loop, `loop` tells you where you are:

| Property | Value |
| --- | --- |
| `loop.index` | Position, starting at 1 |
| `loop.index0` | Position, starting at 0 |
| `loop.revIndex` | Items left, ending at 1 |
| `loop.revIndex0` | Items left, ending at 0 |
| `loop.first` | `true` on the first item |
| `loop.last` | `true` on the last item |
| `loop.length` | Total number of items |

page.kiln:

```kiln
{% for tag in tags %}{{ tag }}{{ loop.last ? "." : ", " }}{% endfor %}
```

Output:

```html
fast, safe, async.
```

## Nested loops

In a nested loop, `loop` refers to the inner loop. To use the outer one, save it first:

```kiln
{% for row in rows %}
	{% set outer = loop %}
	{% for cell in row %}
		{{ outer.index }}.{{ loop.index }}
	{% endfor %}
{% endfor %}
```

Each pass through the loop has its own scope. To build up a value across passes, set the variable before the loop. See [Assigning variables](https://kilnlang.com/docs/language/variables/#assigning-variables).
