# Vertical-Stack, Horizontal-Stack, and Absolute Layout Modes in HKUDS/CLI-Anything: A Complete Guide

> Understand HKUDS/CLI-Anything's vertical-stack, horizontal-stack, and absolute layout modes. Learn how each positioning strategy renders child layers in containers for complete control over your UI.

- Repository: [✨Data Intelligence Lab@HKU✨/CLI-Anything](https://github.com/HKUDS/CLI-Anything)
- Tags: deep-dive
- Published: 2026-08-16

---

**CLI-Anything's layout engine provides three mutually exclusive positioning strategies—`vertical-stack`, `horizontal-stack`, and `absolute`—that determine how child layers are calculated and rendered inside a container.**

The HKUDS/CLI-Anything repository includes a lightweight layout engine in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js) that computes layer positions based on a **layout descriptor**. Each descriptor's `type` field selects one of three layout modes, giving developers declarative control over UI arrangement without manual coordinate calculations—or full control when needed.

---

## Vertical-Stack Layout Mode

The **`vertical-stack`** layout places children **top-to-bottom** inside their container. This mode functions similarly to CSS flexbox with `flex-direction: column`.

### How It Works

In `layoutVerticalStack()` (located in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js)), the engine:

1. Applies padding (`paddingTop`, `paddingBottom`, `paddingHorizontal`)
2. Iterates through `layers`, calling `intrinsicSize()` for each child
3. Computes `x` based on `alignItems` (`left`, `center`, `right`)
4. Increments `cursorY` by `height + gap` for each subsequent child

### Configuration Options

| Property | Type | Description |
|----------|------|-------------|
| `paddingTop` / `paddingBottom` | number | Vertical padding inside the container |
| `paddingHorizontal` | number | Left and right padding |
| `gap` | number | Space between stacked children |
| `alignItems` | string | Horizontal alignment: `left`, `center`, `right` |

### Code Example

```js
const verticalLayout = {
  type: 'vertical-stack',
  paddingTop: 20,
  paddingHorizontal: 10,
  gap: 8,
  alignItems: 'center',
};

const layers = [
  { type: 'text', value: 'Title', fontSize: 24 },
  { type: 'spacer', height: 12 },
  { type: 'text', value: 'Subtitle', fontSize: 14 },
];

const result = computeLayout(layers, verticalLayout, 300, 400);
// Each layer receives calculated y; x is centered within 300px container

```

**Primary use-case:** Stacking rows of UI elements—lists, form fields, vertically arranged icons, or any sequential content flow.

---

## Horizontal-Stack Layout Mode

The **`horizontal-stack`** layout arranges children **left-to-right**, with distribution control via `justifyContent` and cross-axis alignment via `alignItems`.

### How It Works

The `layoutHorizontalStack()` implementation:

1. Gathers intrinsic sizes of all children
2. Recursively lays out any nested groups
3. Computes `startX` and effective gap based on `justifyContent`
4. Outputs each child's final `x`/`y` position

### Configuration Options

| Property | Type | Description |
|----------|------|-------------|
| `paddingHorizontal` / `paddingLeft` / `paddingRight` | number | Horizontal padding |
| `gap` | number | Space between children |
| `justifyContent` | string | Distribution: `start`, `center`, `end`, `space-between` |
| `alignItems` | string | Vertical alignment: `top`, `center`, `bottom` |

### Code Example

```js
const horizLayout = {
  type: 'horizontal-stack',
  paddingHorizontal: 16,
  gap: 12,
  justifyContent: 'space-between',
  alignItems: 'bottom',
};

const layers = [
  { type: 'text', value: '←', fontSize: 18 },
  { type: 'text', value: '→', fontSize: 18 },
];

const result = computeLayout(layers, horizLayout, 400, 100);
// Children spread across 400px width with equal distribution

```

**Primary use-case:** Toolbar buttons, icon rows, navigation elements, or any set of components sharing a common baseline.

---

## Absolute Layout Mode (Default)

The **`absolute`** layout preserves the **exact `x` and `y` coordinates** specified in each layer's definition. No automatic stacking calculations occur.

### How It Works

In `layoutAbsolute()` (source: [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js)), the engine:

- Maps each layer to `{ x: layer.x || 0, y: layer.y || 0, ... }`
- Resolves intrinsic size via `intrinsicSize()` or uses explicit `width`/`height`
- Recursively processes groups without applying additional layout math

### Key Characteristics

- **No padding, gap, or alignment properties apply**
- Each child controls its own position
- Groups are still recursively processed for nested structure

### Code Example

```js
const absoluteLayout = { type: 'absolute' };

const layers = [
  { type: 'text', value: 'Fixed', x: 50, y: 30, fontSize: 16 },
  { type: 'text', value: 'Positioned', x: 150, y: 70, fontSize: 16 },
];

const result = computeLayout(layers, absoluteLayout, 500, 200);
// Positions taken verbatim; no stacking computation

```

**Primary use-case:** Precise graphic designs where layer positions are pre-defined—hand-crafted Sketch artboards, complex visual compositions, or imported design files.

---

## Quick Comparison: Choosing the Right Layout Mode

| Mode | Positioning | Manual Coordinates | Best For |
|------|-------------|-------------------|----------|
| **vertical-stack** | Automatic, top-to-bottom | Not required | Lists, forms, vertical content flows |
| **horizontal-stack** | Automatic, left-to-right | Not required | Toolbars, button groups, icon rows |
| **absolute** | Manual, exact coordinates | Required | Complex designs, imported artboards, pixel-perfect control |

---

## Core Implementation Files

The layout engine is implemented across three key files in the HKUDS/CLI-Anything repository:

- **[`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js)** — Contains `layoutVerticalStack()`, `layoutHorizontalStack()`, `layoutAbsolute()`, and the main `computeLayout()` entry point
- **[`sketch/agent-harness/src/builder.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/builder.js)** — Demonstrates layout engine invocation during Sketch file construction
- **[`sketch/agent-harness/README.md`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/README.md)** — JSON spec examples using all three layout modes

---

## Summary

- **vertical-stack** provides automatic top-to-bottom stacking with `alignItems` for horizontal control
- **horizontal-stack** enables left-to-right distribution with `justifyContent` and `alignItems` for precise alignment
- **absolute** (default) preserves exact `x`/`y` coordinates without computation, ideal for pre-designed layouts
- All three modes are mutually exclusive via the `type` field in the layout descriptor
- The implementation resides in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js) with clear separation between strategies

---

## Frequently Asked Questions

### Can I nest layout modes inside each other?

Yes. The engine recursively processes groups, so a `vertical-stack` can contain child groups that use `horizontal-stack` or `absolute` internally. Each group's layout is computed independently before being positioned by its parent.

### What happens if I omit the `type` field in a layout descriptor?

The engine defaults to `absolute` layout mode, preserving any explicit `x` and `y` coordinates. This ensures backward compatibility and predictable behavior when no stacking is requested.

### Does `justifyContent` work in `vertical-stack` mode?

No. `justifyContent` is specific to `horizontal-stack`. For vertical distribution control, use `paddingTop`, `paddingBottom`, and `gap`. The property sets are intentionally separated to match their respective directional semantics.