Container Relative Frame

Proportional layouts in SwiftUI

published on September 18, 2025

In a previous article, I’ve presented the use of the Layout protocol in SwiftUI by creating a custom proportional layout which can be used to size views proportionally to their container. The results of that layout were rather nice, however in iOS 17, Apple introduced a native solution in SwiftUI, containerRelativeFrame

The modifier

The container relative frame modifier has two variants

containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 0)
// and
containerRelativeFrame(.horizontal) { length, axis in length * 0.75 }

The first one can be used to size the view proportionally. Count is the number of imaginary columns the container is divided into while span is the number of columns the view will occupy. Spacing tells the modifier how much space to subtract from the length, but doesn’t actually introduce any space between views. That has to be controlled from the container

The second version takes a callback, in which you can perform any custom logic to determine the final size based on the container size.

The callback also receives the axis, so if you specify two axis in the first parameter, the callback will be executed twice and you can perform different logic for different axis

But what is a container?

The only limitation of the container relative frame is that you can’t control what is a container. According to apple's documentation, at the time of writing this article, a container can be the window presenting the view, a scroll view or any navigation component (split view column, tab view frame, etc)

Full example

Let's see a full example

ScrollView {
    HStack {
        Color.green
            .containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 0)
        Color.red
            .containerRelativeFrame(.horizontal, count: 4, span: 1, spacing: 0)
        Color.green
            .containerRelativeFrame(.horizontal) { length, _ in length * 0.75 }
    }
}
Follow me on X