# How to Nest Multiple StackFrameLayouts to Build Complex Layouts in FrameLayoutKit

> Learn how to nest multiple StackFrameLayouts in FrameLayoutKit to build intricate UI layouts. Discover recursive nesting for complex hierarchies and dynamic UI creation.

- Repository: [Nam Kennic/framelayoutkit](https://github.com/kennic/framelayoutkit)
- Tags: how-to-guide
- Published: 2026-03-05

---

**FrameLayoutKit enables complex UI hierarchies by allowing HStackLayout, VStackLayout, and ZStackLayout instances to be nested recursively inside one another, treating each child stack as a standard FrameLayout that participates in the parent stack's layout calculations via the `add(_:)` method in [`StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/StackFrameLayout.swift).**

The `kennic/FrameLayoutKit` library provides a declarative layout system for iOS and macOS that simplifies view construction through composable stacks. When you nest multiple StackFrameLayouts, you create sophisticated interface structures—such as vertical lists containing horizontal rows or overlay groups—while maintaining clean, readable source code that scales with interface complexity.

## The Inheritance Architecture Enabling Nesting

FrameLayoutKit's stack types—**`HStackLayout`**, **`VStackLayout`**, and **`ZStackLayout`**—are all subclasses of **`StackFrameLayout`**, which inherits from the base **`FrameLayout`** class defined in [`FrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayout.swift). Because every stack is ultimately a `FrameLayout`, the parent stack can treat nested stacks exactly like standard views. This polymorphic design allows the `add(_:)` method to accept any `FrameLayout` subclass, storing it in the internal `frameLayouts` array and adding it as a child view via `addSubview(_:)`.

## How StackFrameLayout.swift Detects and Stores Child Stacks

The nesting logic resides in [`StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/StackFrameLayout.swift). When you call `add(_:)` to insert a sub-stack, the implementation performs a type check to determine if the supplied object is an existing `FrameLayout` instance:

```swift
if let frameLayout = view as? FrameLayout, frameLayout.superview == nil {
    applyCommonAttributes(to: frameLayout)
    frameLayouts.append(frameLayout)
    addSubview(frameLayout)
    return frameLayout
}

```

This check ensures the child is unowned (`superview == nil`) before appending it to `frameLayouts` and applying common attributes via **`applyCommonAttributes(to:)`**. By returning the `frameLayout` directly rather than wrapping it, the library preserves the full layout capabilities of nested stacks.

## Recursive Layout Calculation

During the layout phase, each stack executes `layoutSubviews()` to measure and position its children. The method calls `sizeThatFits` and `layoutSubviews` on every child in the `frameLayouts` array. If a child is itself a `StackFrameLayout`, the same measurement logic runs recursively, creating a depth-first layout pass through the entire tree. This recursive approach ensures that nested stacks calculate their internal sizes before parents distribute available space.

## Key Behaviors for Complex Nesting

Several mechanisms in [`StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/StackFrameLayout.swift) and [`FrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayout.swift) work together to support deep nesting:

- **Common attribute propagation**: The `applyCommonAttributes(to:)` method copies debugging overlays, skeleton loading states, and caching behaviors from parent to child stacks automatically.
- **Flexible frame distribution**: When `isFlexible` is true, nested stacks participate in the parent's space distribution using `flexibleRatio`, allowing a nested stack to expand and fill remaining dimensions.
- **Justification and distribution**: Parent stacks control alignment via `distribution` and `isJustified` properties, positioning nested stacks according to the parent's layout rules regardless of the child's internal complexity.
- **Overlapped mode**: Setting `isOverlapped` to true (used by `ZStackLayout`) stacks children on top of each other, enabling overlay layouts where inner stacks sit on shared layers.

## Practical Implementation: Building Deep Hierarchies

FrameLayoutKit provides two syntax styles for declaring nested structures: a trailing-closure DSL (defined in `StackFrameLayout+DSL.swift`) and a chainable builder pattern (defined in `StackFrameLayout+Chainable.swift`).

### DSL Syntax Example

```swift
import FrameLayoutKit
import UIKit

// MARK: - Example 1 – Vertical list of horizontal rows
let root = VStackLayout { vStack in
    // Row 1
    vStack.add(
        HStackLayout { hStack in
            hStack.add(UILabel())   // label 1
                .fixedWidth(80)
            hStack.add(UIButton())  // button 1
                .fixedWidth(120)
        }
        .spacing(8)                 // spacing inside the row
    )
    
    // Row 2 (flexible height)
    vStack.add(
        HStackLayout { hStack in
            hStack.add(UILabel())
                .flexible()         // takes remaining vertical space
            hStack.add(UIButton())
                .fixedWidth(120)
        }
        .spacing(8)
    )
    
    // Row 3 – overlay badge using ZStack
    vStack.add(
        ZStackLayout { zStack in
            // Background view (full width)
            zStack.add(UIView())
                .fixedHeight(40)
                .backgroundColor(.lightGray)
            // Badge on top‑right corner
            zStack.add(UILabel())
                .fixedSize(CGSize(width: 24, height: 24))
                .alignment(.top, .right) // custom extension for alignment
        }
        .spacing(0)
    )
}
.root?.backgroundColor = .white

```

### Chainable Syntax Example

```swift
// MARK: - Example 2 – Chainable syntax (same layout as above, shorter)
let root2 = VStackLayout()
    .spacing(12)
    .add(
        HStackLayout()
            .spacing(8)
            .add(UILabel()).fixedWidth(80)
            .add(UIButton()).fixedWidth(120)
    )
    .add(
        HStackLayout()
            .spacing(8)
            .add(UILabel()).flexible()
            .add(UIButton()).fixedWidth(120)
    )
    .add(
        ZStackLayout()
            .add(UIView()).fixedHeight(40).backgroundColor(.lightGray)
            .add(UILabel()).fixedSize(CGSize(width: 24, height: 24)).alignment(.top, .right)
    )

```

Both examples produce the same visual hierarchy:

```

VStack
 ├─ HStack (row 1)
 │    ├─ UILabel
 │    └─ UIButton
 ├─ HStack (row 2, flexible height)
 │    ├─ UILabel (flexible)
 │    └─ UIButton
 └─ ZStack (row 3)
      ├─ UIView (background)
      └─ UILabel (badge overlay)

```

## Summary

- StackFrameLayouts nest because they inherit from `FrameLayout`, allowing type-safe insertion via `add(_:)` in [`StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/StackFrameLayout.swift).
- The `frameLayouts` array stores children, and `applyCommonAttributes(to:)` propagates settings down the tree.
- Layout calculates recursively through `layoutSubviews()` and `sizeThatFits`, with parent stacks determining final positions.
- Flexible ratios, distribution rules, and overlapped modes give nested stacks adaptive sizing and positioning capabilities.
- DSL and chainable syntax in `StackFrameLayout+DSL.swift` and `StackFrameLayout+Chainable.swift` provide ergonomic APIs for deep hierarchies.

## Frequently Asked Questions

### Can I nest a ZStackLayout inside an HStackLayout or VStackLayout?

Yes. Because `ZStackLayout` inherits from `StackFrameLayout`, which inherits from `FrameLayout`, it can be added to any parent stack using the `add(_:)` method. The ZStack will be measured and positioned according to the parent stack's distribution rules while maintaining its own overlapped layout behavior for its children.

### How deep can I nest StackFrameLayouts without performance issues?

There is no artificial limit enforced by the library. Layout performance depends on the complexity of the view hierarchy and the cost of `sizeThatFits` calculations for leaf views. Since FrameLayoutKit uses a recursive layout pass that runs on the main thread, excessively deep trees (dozens of levels) may impact scroll performance, but typical interface depths of 3-10 levels execute efficiently.

### Do nested stacks automatically inherit spacing and alignment from their parents?

Nested stacks do not automatically inherit layout-specific properties like `spacing` or `distribution`. However, they do inherit common attributes—including debugging overlays, skeleton loading states, and caching behaviors—via the `applyCommonAttributes(to:)` method called during `add(_:)`. Each stack maintains independent control over its own internal layout parameters.

### What is the difference between adding a raw UIView versus adding a StackFrameLayout as a child?

When you add a raw `UIView`, `StackFrameLayout` wraps it in a `FrameLayout` instance internally. When you add an existing `StackFrameLayout` (or `HStackLayout`/`VStackLayout`/`ZStackLayout`), the parent recognizes it via the `as? FrameLayout` type check and appends it directly to `frameLayouts` without wrapping, preserving the child's layout logic and avoiding unnecessary container overhead.