# How to Implement Overlapping Views in FrameLayoutKit: ZStackLayout vs isOverlapped Property

> Learn how to implement overlapping views in FrameLayoutKit using ZStackLayout or the isOverlapped property. Easily toggle overlap mode with the overlapped method.

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

---

**ZStackLayout forces overlapping behavior by default, while the `isOverlapped` property lets you toggle overlap mode on any existing StackFrameLayout subclass using the chainable `overlapped(_:)` method.**

FrameLayoutKit provides two distinct approaches for creating overlapping views in iOS and macOS applications. Whether you need a dedicated Z-stack container or want to enable overlap on an existing horizontal or vertical stack, understanding the difference between `ZStackLayout` and the `isOverlapped` property is essential for building layered user interfaces.

## Understanding the Overlapping Views Architecture

### The isOverlapped Flag

Located in [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift) at line 22, the `isOverlapped` property is defined as:

```swift
public var isOverlapped: Bool = false { didSet { setNeedsLayout() } }

```

When set to `true`, the layout engine treats every child as occupying the full container dimensions. The `sizeThatFits` and `layoutSubviews` methods check this flag (visible at line 19 in `sizeThatFits`, lines 20-23 in the vertical branch, and lines 21-23 in the horizontal branch) and skip normal stacking calculations, aligning each subview to the container's origin.

### ZStackLayout Implementation

The `ZStackLayout` class, found at lines 96-100 in [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift), is a concrete subclass that hardcodes overlapping behavior:

```swift
public class ZStackLayout: StackFrameLayout {
    public override init() {
        super.init()
        axis = .vertical
        isOverlapped = true
    }
}

```

Additionally, its overridden `add(_:)` method at lines 16-18 automatically makes each child flexible by calling `super.add(view).flexible()`, ensuring children stretch to fill the available space.

## Implementing Overlapping Views with ZStackLayout

For simple overlapping scenarios, use the `ZStackLayout` or its DSL wrapper `ZStackView`:

```swift
// ZStackView is a DSL wrapper around ZStackLayout
let overlapping = ZStackView {
    UILabel()                // first child – placed at origin
    UIImageView(image: img)  // second child – drawn on top of the label
    UIButton(type: .system)  // third child – topmost layer
}

```

Under the hood, `ZStackView` inherits from `ZStackLayout`, which forces `isOverlapped = true` during initialization. The DSL builder calls the overridden `add(_:)` method, making every child flexible so they all share the same frame dimensions. Because overlapping is enabled, the layout engine skips spacing calculations and positions each child at the container's origin, creating the classic Z-order stacking effect where later children render on top of earlier ones.

## Enabling Overlap on Existing Stacks with isOverlapped

If you already use `HStackLayout` or `VStackLayout` and need to toggle overlapping behavior, set the `isOverlapped` property directly:

```swift
let overlappedH = HStackLayout()
    .overlapped(true)          // chainable setter
    .add(UILabel())
    .add(UIImageView(image: img))
    .add(UIButton(type: .system))

```

The `overlapped(_:)` method, defined at line 28 in `FrameLayoutKit/Classes/Extensions/StackFrameLayout+Chainable.swift`, provides a fluent interface:

```swift
@discardableResult public func overlapped(_ value: Bool) -> Self {
    self.isOverlapped = value
    return self
}

```

Unlike `ZStackLayout`, enabling `isOverlapped` on a standard stack does **not** automatically make children flexible. You must explicitly call `.flexible()` on each child if you want them to stretch and fill the container:

```swift
stack.add(view).flexible()

```

If you prefer a DSL-style block, use the generic `StackFrameLayout` DSL wrapper and set the flag inside the block:

```swift
let overlappedV = VStackView {
    UILabel()
    UIImageView(image: img)
    UIButton(type: .system)
}
.overlapped(true)        // works because VStackView inherits from StackFrameLayout

```

## When to Use Each Approach for Overlapping Views

Choose the appropriate method based on your architectural requirements:

- **Use `ZStackLayout`** when you need a dedicated container for overlapping views. It is self-documenting, forces overlap by default, and automatically makes children flexible. Ideal for layered UI elements like badges on icons or background overlays.

- **Use `isOverlapped`** when you need to toggle overlapping behavior dynamically on an existing `HStackLayout` or `VStackLayout`. This avoids refactoring your layout hierarchy and allows runtime switching between stacked and overlapped arrangements.

- **Combine approaches** by nesting a `ZStackLayout` inside a normal stack to isolate overlapping regions within a larger non-overlapping layout.

## Key Source Files and Implementation Details

Understanding the implementation helps debug layout issues:

| File | Key Implementation |
|------|-------------------|
| [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift) | Defines `isOverlapped` at line 22 with `didSet { setNeedsLayout() }`. Contains `ZStackLayout` subclass at lines 96-100 and the flexible `add(_:)` override at lines 16-18. |
| [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift) | Layout logic branches for `isOverlapped` in `sizeThatFits` (line 19) and `layoutSubviews` (vertical branch lines 20-23, horizontal branch lines 21-23). |
| `FrameLayoutKit/Classes/Extensions/StackFrameLayout+Chainable.swift` | Provides `overlapped(_:)` at line 28 for fluent API usage. |

Both approaches rely on the same underlying engine: when `isOverlapped` is true, the layout skips spacing calculations and positions each child at the container's origin, creating the overlapping effect.

## Summary

- **`ZStackLayout`** provides a purpose-built solution for overlapping views, automatically setting `isOverlapped = true` and making all children flexible.
- **`isOverlapped`** is a boolean flag available on all `StackFrameLayout` subclasses that toggles overlap mode, accessible via the chainable `overlapped(_:)` method.
- When `isOverlapped` is enabled, the layout engine treats every child as occupying the full container frame, skipping normal stacking calculations.
- Choose `ZStackLayout` for dedicated Z-axis containers; use `isOverlapped` to dynamically enable overlap on existing horizontal or vertical stacks.

## Frequently Asked Questions

### What is the difference between ZStackLayout and setting isOverlapped on a VStackLayout?

`ZStackLayout` is a specialized subclass that hardcodes `axis = .vertical` and `isOverlapped = true` during initialization, and automatically makes every added child flexible via its overridden `add(_:)` method. Setting `isOverlapped` on a `VStackLayout` only changes the layout behavior to overlap; it does not modify child flexibility or axis settings, giving you more manual control but requiring explicit configuration for each child.

### Does enabling isOverlapped affect how children are sized?

Yes. When `isOverlapped` is true, the layout engine defined in [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift) skips normal stacking mathematics and treats each child as occupying the full container bounds. In `ZStackLayout`, children are automatically made flexible. When manually enabling `isOverlapped` on other stacks, you must explicitly call `.flexible()` on each child if you want them to stretch and fill the container dimensions.

### Can I toggle overlapping behavior at runtime?

Yes. Because `isOverlapped` is defined in [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift) with a `didSet` observer that calls `setNeedsLayout()`, you can change its value at any time. The chainable `overlapped(_:)` method returns `Self`, allowing you to modify the flag in response to user interactions or state changes, with the layout automatically invalidating and re-rendering on the next layout cycle.

### Where is the overlapping logic actually implemented in the source code?

The core logic resides in [`FrameLayoutKit/Classes/StackFrameLayout.swift`](https://github.com/kennic/framelayoutkit/blob/main/FrameLayoutKit/Classes/StackFrameLayout.swift). The `isOverlapped` property is defined at line 22. The layout engine checks this flag in `sizeThatFits` (around line 19) and `layoutSubviews` (in both vertical and horizontal branches, lines 20-23 and 21-23 respectively), skipping spacing calculations and aligning children to the container origin when enabled.