---
title: "Introduction"
description: "An introduction to the Field Guide and the layout system in SwiftUI"
url: https://www.swiftuifieldguide.com/layout/introduction
markdown_url: https://www.swiftuifieldguide.com/layout/introduction.md
---
> Convenience Markdown export of the HTML page. Interactive samples, diagrams, and visualizations stay on the canonical page.
# Introduction

SwiftUI is a declarative framework for building user interfaces. When coming from UIKit, SwiftUI is very different. There is little knowledge that we can transfer from UIKit to SwiftUI — the layout system is different, the state system is different, animations are different, and so on.

This guide is designed to help understand the layout system in SwiftUI. We hope that the visual examples invite to explore SwiftUI's views and modifiers. The interactive examples do not run actual SwiftUI code, but are reimplemented in a simplified SwiftUI port. As such, they might not always match SwiftUI in a pixel-perfect way. (However, if our port behaves differently, we do consider it a bug.)

## View Trees {#viewTrees}

To understand the SwiftUI layout system, it is essential to understand how the code we write translates into a tree. For example, consider the following code:

> Pretty-printed code from Sample Background Padding

```swift
Text("Hello, World!")
    .padding()
    .background(Color.accentColor)
```

> Interactive example on HTML page: Sample Background Padding.

In the example above, the order of the modifiers is critical. If we switch the order of the background and [padding](/layout/padding) modifiers, the background will only be the size of the text, and the padding is added outside of the background.

The view builder syntax used in SwiftUI is designed to construct view trees. In the example below, we can see how two very different view trees get constructed when the order of the modifiers changes. In one case, the background is applied to the padded text, whereas in the other case, the padding is added to the text with the background.

> Pretty-printed code from Sample Background Padding Tree

```swift
Text("Hello, World!")
    .padding()
    .background(Color.accentColor)
```

> Interactive example on HTML page: Sample Background Padding Tree.

Throughout this guide, we show trees for the views we construct. When we're debugging our own views, it can often be helpful to think about the view tree that gets constructed. Understanding view trees is not only important for layout, but is a necessary skill for understanding the state system, the animation system, the environment and much more.

## Proposing and Reporting {#proposing}

The essence of SwiftUI's layout system is very simple: a parent proposes a size to its child, and the child reports a size. In practice, however, the layout system is not always easy to work with. This is because every view in SwiftUI can potentially have a different algorithm for choosing its size based on the proposal.

In the example below, we can see the proposing and reporting in action. At first, a size of 200×200 is proposed to the background modifier. The background modifier then proposes that same size to its primary child, the padding. The padding subtracts 32 from the width and height, and proposes the smaller size to the text. The text reports its intrinsic size, and the size is then reported back up the tree. The padding adds 32 to the width and height, and reports its size to the background. The background then reports its size to the parent. Finally, to render the secondary child of the background, the size of the primary child (the padded text) is proposed to the color.

> Pretty-printed code from Sample Background Padding Layout

```swift
Text("Hello, World!")
    .padding()
    .background(Color.accentColor)
```

> Interactive example on HTML page: Sample Background Padding Layout.

Views have very different behaviors when it comes to proposing and reporting. For example, a regular [image view](/layout/image) ignores the proposed size but returns its intrinsic size. An [aspect ratio](/layout/aspect-ratio) modifier can propose twice to its child — once to figure out the underlying aspect ratio and once to actually render the child. A [shape](/layout/shape) such as a rectangle unconditionally accepts the proposed size. Understanding how different views respond to proposed sizes is essential for building complex layouts. There are no requirements on the response: a view can accept, ignore or do something else with the proposed size.

## Theory: Attribute Graph {#attributeGraph}

The layout system in SwiftUI is based on a tree of views. These view trees get constructed from the code we write. The layout system then constructs an *attribute graph* from the view tree. The process of constructing the attribute graph is almost completely opaque. In our book [Thinking in SwiftUI](https://www.objc.io/books/thinking-in-swiftui/), we go over the process of how this works. The WWDC video [Explore SwiftUI animation](https://developer.apple.com/wwdc23/10156) is currently the only public available first-party documentation that explains the attribute graph.

There are a few useful things to know about the attribute graph. It is called the attribute graph because it is based on [attribute grammars](https://en.wikipedia.org/wiki/Attribute_grammar). In essence, when we view our SwiftUI code as a tree, certain properties get passed down the tree, and other properties get reported back up the tree.

A value that gets passed down the tree is called an *inherited attribute*. Examples include the proposed size, the environment, the safe area and the current [transaction](https://www.objc.io/blog/2021/11/25/transactions-and-animations/). Properties that are reported back up the tree are called *synthesized attributes*. Examples include the reported size, [alignment guides](/layout/alignment), [layout priorities](/layout/hstack) and preferences. When writing SwiftUI, we find that it can sometimes be helpful to think about whether a property is inherited or synthesized.
