Skip to content

Layout & Sizing ​

Panels are laid out with stacks, the same model SwiftUI and Figma's auto layout use. You don't position views at coordinates. You put them in stacks, and each stack arranges its children in a row, a column or layers. Stacks can hold other stacks, so a few levels are enough for most panels.

The three stacks ​

StackArranges its childrenTypical use
VStack (Vertical)top to bottoma card: title, text, button
HStack (Horizontal)left to righta row of buttons, an icon beside a label
ZStack (Depth)on top of each othertext over an image, a badge in a corner

Every panel has one root view, and it is almost always a stack. A new panel starts with a VStack.

Select a stack and change its Direction to turn it into another kind of stack without rebuilding it. Switching between Vertical and Horizontal keeps the alignment and spacing; switching to or from Depth resets them, because a ZStack aligns differently.

To group views you've already placed, right-click one and choose Wrap into… a VStack, HStack or ZStack. Dissolve Stack does the opposite for a stack with a single child.

A worked example ​

A product card with an image on top, a title, a line of text and two buttons side by side:

VStack  (alignment Fill, spacing 12, padding 16)
├── Image        (Fixed 280 × 160)
├── Label        "**Lounge Chair**"
├── Label        "Oak and wool, made in Berlin."
└── HStack       (distribution Fill Equally, spacing 8)
    ├── Button   "Colours"
    └── Button   "Details"

The VStack's Fill alignment stretches every row to the card's width, and Fill Equally gives both buttons the same width.

Stack settings ​

VStack and HStack:

  • Alignment – where children sit across the stack: horizontally in a VStack, vertically in an HStack. Leading, Center and Trailing are for a VStack; Top, Center and Bottom are for an HStack. Fill stretches every child to the stack's full width (VStack) or height (HStack). In an HStack, Leading means Top and Trailing means Bottom.
  • Distribution – how children share the stack's length when there is room to spare. Fill lets them keep their own sizes, with any Spacer or Fill-sized child taking up the rest. Fill Equally makes every child the same length – the usual choice for a row of equal buttons.
  • Spacing – the gap between neighbouring children, 0–200 pt. New stacks use 8.

A new VStack starts with Fill alignment; a new HStack starts centred.

ZStack:

  • Alignment – where smaller children sit inside the ZStack: Center, an edge (Top, Bottom, Leading, Trailing) or a corner (Top Leading, Top Trailing, Bottom Leading, Bottom Trailing). Children are layered in hierarchy order, so the last child is drawn on top.

A ZStack doesn't take its size from its children. Give it a Fixed size, or Fill, so its children have an area to align within.

Spacers and dividers ​

  • Spacer – an empty, flexible gap inside a stack. It grows to take up the free space, so a Spacer between two buttons pushes them to opposite ends. Several Spacers in one stack share the free space equally. Min Length sets the smallest it may become; unset, it keeps at least 8 pt.
  • Divider – a thin line between views. Set its Thickness (0.5–8 pt) and its Color in Appearance Overrides.

Sizing ​

Every view except a Spacer has a Sizing setting in its Layout section:

  • Intrinsic – the view is as big as its content: a label as big as its text, a button as big as its title plus padding.
  • Fill – the view expands to take the space its stack offers, in both directions.
  • Fixed – an exact width and height in points.

Some views have no natural size, so they offer only Fill and Fixed: Slider, Progress View, Text Field, Divider, Web View and Shape. New views start with a sensible size: Images at 200 × 200 pt, Shapes at 100 × 100 pt, and Sliders, Progress Views, Text Fields, Dividers and Web Views at Fill.

A view never grows past the stack it sits in. A long label in a narrow column wraps instead of spilling out of the panel.

Max Width and Max Height ​

Max Width and Max Height cap a view's size on top of its sizing mode, the way max-width works on the web:

  • a Fill label with Max Width 400 stretches with the panel but stops at 400 pt, which keeps long lines readable
  • an Intrinsic image with Max Height 120 keeps its natural size until it would get taller than 120 pt

The caps appear only for an axis that isn't Fixed. Spacers and Dividers don't have them.

Padding ​

Padding is space between a view's edge and its content, set separately for top, bottom, leading and trailing. It sits inside the view's background: a button's fill, border and rounded corners include its padding. On a stack, padding insets all of its children – the usual way to give a card breathing room.

Most views start with no padding. Buttons with a title, and Custom toggles with a title, start with 8 pt top and bottom and 12 pt leading and trailing.

Padding isn't offered on Sliders, Progress Views, Dividers, Spacers, Web Views and Switch-style toggles, because those controls can't apply it. Wrap one in a stack and pad the stack instead.

Offset ​

Offset nudges a view by a number of points without changing the layout: the view moves, and everything around it stays where it was. Use it for fine adjustments, like pulling a badge slightly over the edge of an image. To move views relative to each other, change the stacks instead.

Hiding and disabling views ​

Each view's State section has two switches:

  • Hidden – removes the view from the layout entirely; its neighbours close the gap. The hierarchy marks hidden views with an eye icon.
  • Disabled – keeps the view visible but dimmed to 40 % and unresponsive to touches.

To show or hide views while the experience runs, use a script – see Interaction.