> For the complete documentation index, see [llms.txt](https://docs.flatredball.com/gum/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flatredball.com/gum/code/layout/stacking.md).

# Stacking

## Introduction

Gum supports creating vertical and horizontal stacks of children. Stacked children can also be wrapped and support spacing between each item.

This document provides a deep dive into Gum stacking behavior, which is the default behavior for [StackPanel](/gum/code/controls/stackpanel.md), [ItemsControl](/gum/code/controls/itemscontrol.md), and [ListBox](/gum/code/controls/listbox.md).

## Using StackPanel for Stacking

The `StackPanel` provides stacking behavior for its children. The following code shows how to add stacked `Buttons` to a `StackPanel`:

```csharp
// Initialize
var stackPanel = new StackPanel();
stackPanel.AddToRoot();
stackPanel.Anchor(Gum.Wireframe.Anchor.Center);

for(int i = 0; i < 10; i++)
{
    var button = new Button();
    stackPanel.AddChild(button);
    button.Text = $"Button {i}";
}
```

<figure><img src="/files/iKAtUUhiJeiFwg9nWOIP" alt=""><figcaption></figcaption></figure>

StackPanel exposes some of the stack-related properties; however, we will be accessing its Visual to have full control over stacking for the remainder of this documentation.

## Adding Spacing with StackSpacing

The StackSpacing variable can be used to add spacing between each stacked item, as shown in the following code:

<pre class="language-csharp"><code class="lang-csharp">// Initialize
var stackPanel = new StackPanel();
stackPanel.AddToRoot();
stackPanel.Anchor(Gum.Wireframe.Anchor.Center);

<strong>var stackPanelVisual = stackPanel.Visual;
</strong><strong>stackPanelVisual.StackSpacing = 4;
</strong>
for(int i = 0; i &#x3C; 10; i++)
{
    var button = new Button();
    stackPanel.AddChild(button);
    button.Text = $"Button {i}";
}
</code></pre>

<figure><img src="/files/qTD0hny8L9my7spbtuTf" alt=""><figcaption><p>Buttons with spacing</p></figcaption></figure>

## Horizontal Stacking

We can change the stacking direction by changing the `ChildrenLayout` property as shown in the following code. Note that the `Buttons` have been made narrower so they all fit on screen.

<pre class="language-csharp"><code class="lang-csharp">// Initialize
var stackPanel = new StackPanel();
stackPanel.AddToRoot();
stackPanel.Anchor(Gum.Wireframe.Anchor.Center);

var stackPanelVisual = stackPanel.Visual;
<strong>stackPanelVisual.ChildrenLayout = 
</strong><strong>    Gum.Managers.ChildrenLayout.LeftToRightStack;
</strong>
for(int i = 0; i &#x3C; 10; i++)
{
    var button = new Button();
<strong>    button.Width = 60;
</strong>    stackPanel.AddChild(button);
    button.Text = $"Button {i}";
}
</code></pre>

<figure><img src="/files/YLl3B76Prbe9sf80oLwi" alt=""><figcaption><p>Buttons stacking horizontally</p></figcaption></figure>

## Wrapping

Stacked children can also be wrapped horizontally. Before wrapping can happen, the parent `StackPanel` must not depend on its children's size in its *primary* stacking direction. For example, if a `StackPanel` is using its default vertical stacking, then its `Height` must not depend on its children - otherwise it stretches indefinitely to contain its children.

The following code shows how to set an absolute Height on the parent `StackPanel` and enable wrapping:

```csharp
// Initialize
var stackPanel = new StackPanel();
stackPanel.AddToRoot();
stackPanel.Anchor(Gum.Wireframe.Anchor.Center);
stackPanel.HeightUnits = Gum.DataTypes.DimensionUnitType.Absolute;
stackPanel.Height = 150;

var stackPanelVisual = stackPanel.Visual;

stackPanelVisual.WrapsChildren = true;

for(int i = 0; i < 10; i++)
{
    var button = new Button();
    stackPanel.AddChild(button);
    button.Text = $"Button {i}";
}
```

<figure><img src="/files/yF91GAXvXmD7EzcIt1AO" alt=""><figcaption><p>Children stacked vertically and wrapped</p></figcaption></figure>

Notice that since the `StackPanel` has had `Anchor(Anchor.Center)` called, it remains centered as it wraps and expands horizontally.

## Bottom-Up and Right-to-Left Stacking

A `StackPanel's` `Visual` only provides two possible stacking modes:

* `ChildrenLayout.TopToBottomStack` (default)
* `ChildrenLayout.LeftToRightStack`

There is no dedicated "bottom-up" or "right-to-left" mode, but you can create either by combining `Anchor` (or `Dock`) with `ChildrenLayout`. In both cases the `StackPanel` is anchored to one edge, so it stays pinned to that edge and grows in the opposite direction as children are added.

### Bottom-Up Stacking

The following code creates a bottom-up stack similar to a chat room or command line. The `StackPanel` is anchored to the bottom, so newly-added children appear at the bottom and older children are pushed up:

```csharp
// Class scope
StackPanel stackPanel;

protected override void Initialize()
{
    GumUI.Initialize(this);

    stackPanel = new StackPanel();
    stackPanel.AddToRoot();
    stackPanel.Anchor(Gum.Wireframe.Anchor.Bottom);

    base.Initialize();
}

protected override void Update(GameTime gameTime)
{
    GumUI.Update(gameTime);

    if(GumUI.Keyboard.KeyPushed(Microsoft.Xna.Framework.Input.Keys.Enter))
    {
        var label = new Label();
        stackPanel.AddChild(label);
        int index = stackPanel.Children.Count;
        label.Text = $"{index}: Added at {System.DateTime.Now}";
    }

    base.Update(gameTime);
}
```

<figure><img src="/files/0jbnCQSnrO8NNXaetClj" alt=""><figcaption><p>Bottom-up stack</p></figcaption></figure>

### Right-to-Left Stacking

Right-to-left stacking uses the same approach horizontally: set `ChildrenLayout` to `LeftToRightStack` and anchor the `StackPanel` to the right. The stack stays pinned to the right edge and grows toward the left as children are added, so the newest item appears on the right:

```csharp
// Class scope
StackPanel stackPanel;

protected override void Initialize()
{
    GumUI.Initialize(this);

    stackPanel = new StackPanel();
    stackPanel.AddToRoot();
    stackPanel.Anchor(Gum.Wireframe.Anchor.Right);
    stackPanel.Visual.ChildrenLayout =
        Gum.Managers.ChildrenLayout.LeftToRightStack;

    base.Initialize();
}

protected override void Update(GameTime gameTime)
{
    GumUI.Update(gameTime);

    if(GumUI.Keyboard.KeyPushed(Microsoft.Xna.Framework.Input.Keys.Enter))
    {
        var label = new Label();
        stackPanel.AddChild(label);
        int index = stackPanel.Children.Count;
        label.Text = $"Item {index}";
    }

    base.Update(gameTime);
}
```

{% hint style="warning" %}
TODO: Add a gif showing right-to-left stacking (newest item appearing on the right, older items pushed to the left).
{% endhint %}

## Evenly-Sized Stacked Children

Stacking can be combined with ratio sizes to create evenly-sized children.

If children use a `Height Units` of `Ratio`, then they are sized according to the size of their parent and the size of their siblings. Since children depend on the parent's size, the parent should not depend on its children for its height.

The following code creates buttons which all share the height of their parent StackPanel.

```csharp
// Class scope
StackPanel stackPanel;

protected override void Initialize()
{
    GumUI.Initialize(this);

    stackPanel = new StackPanel();
    stackPanel.AddToRoot();
    stackPanel.Anchor(Gum.Wireframe.Anchor.Center);
    stackPanel.HeightUnits = Gum.DataTypes.DimensionUnitType.Absolute;
    stackPanel.Height = 200;

    base.Initialize();
}

protected override void Update(GameTime gameTime)
{
    GumUI.Update(gameTime);
    if(GumUI.Keyboard.KeyPushed(Microsoft.Xna.Framework.Input.Keys.Enter))
    {
        var button = new Button();
        stackPanel.AddChild(button);
        button.HeightUnits = Gum.DataTypes.DimensionUnitType.Ratio;
        button.Height = 1;
        button.Text = $"Button {stackPanel.Children.Count}";
    }
    base.Update(gameTime);
}
```

<figure><img src="/files/JvaBDrSsIJehUYz8hX8a" alt=""><figcaption><p>Children Buttons stacked with Ratio size</p></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flatredball.com/gum/code/layout/stacking.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
