Skip to content

Prepare your toolbars for vertical layout

MajorNeeds iOS 27.1 SDKnavigation

What you see

Toolbar labels truncate, custom bar views render sideways or clipped, or too many items collapse into an overflow menu.

Horizontal bars versus the iPhone Duo vertical barOn a standard iPhone, navigation and toolbar controls sit in horizontal rows at the top and bottom of the screen. On iPhone Duo, those controls share a single vertical region down one side, leaving the full height for content. This applies on the outer display and on the inner display in landscape; the inner display in portrait keeps horizontal bars.contentStandard iPhonebars run horizontally4 items fit comfortablyfull height for contentiPhone Duo inner, landscapeone shared vertical regionfewer fit — priorities decide which
Navigation, toolbar and tab bar controls share the same vertical region, on the closed outer display as well as the inner display in landscape. Because a column holds less than a row, items overflow sooner — which is what visibilityPriority is for.

Building against the iOS 27.1 SDK changes how bars are laid out on iPhone Duo: navigation, toolbar, and tab bar controls share a single vertical region at the side, preserving vertical space for content. Picture your existing bars rotated ninety degrees into a column.

Where it applies

Display and orientation Bar placement
Outer display (closed) Side, on the right — the outer display is wider and shorter than other iPhones
Inner display, landscape Side — kept there so controls stay where they were when closed
Inner display, portrait Horizontal — there is enough height for standard bars

Every pose except the inner display in portrait puts bars at the side, so this is not a landscape edge case: the closed device shows a vertical bar in both orientations. In Split View on the inner display, each app places its controls along its own outer edge. Items overflow most often on the outer display in landscape, and also when other interface competes for the space, such as the keyboard, or Picture in Picture on the open device in portrait.

What you get automatically

Your existing layout maps across directly. Toolbar buttons from the top of the screen move to the top of the column, buttons from the bottom move to the bottom, and a tab bar stays bottom-aligned. Items too wide for the column, such as a text button or a segmented control, stay in the navigation bar.

Standard containers participate without code changes. Use UINavigationController and UITabBarController, or their SwiftUI equivalents, and the system handles placement. Custom UIToolbar content is not considered for this treatment.

The bar stays on the same side in right-to-left languages, because it is aligned with the hardware rather than the reading direction. In a split view only the detail column participates, and inspectors do not get a bar of their own.

Controlling placement

Order matters in a vertical bar. The top is reserved for primary navigation such as Back or Close, followed directly by prominent actions such as Done. Your remaining items keep their original groups, with a vertical space separating what came from the top bar and what came from the bottom bar:

.toolbar {
    // Primary navigation: first in the column
    ToolbarItem(placement: .cancellationAction) { CloseButton() }

    // Prominent action: directly after navigation
    ToolbarItem(placement: .topBarPinnedTrailing) { DoneButton() }
}
// UIKit
navigationItem.leftItemsSupplementBackButton = false
navigationItem.leadingItemGroups = [UIBarButtonItemGroup(…)]
navigationItem.pinnedTrailingGroup = UIBarButtonItemGroup(…)

A navigation controller adds the Back button for you. Use a leading item only for a custom Back or Close button, and keep leftItemsSupplementBackButton at its default of false.

Items are not rotated. The system decides, item by item, whether each one belongs on the vertical axis or stays in a horizontal bar: items with a symbol move to the side, text-only items stay horizontal, and custom views stay horizontal by default. axisBehavior overrides that choice:

.axisBehavior(.verticalPreferred)   // let a custom view join the vertical bar
.axisBehavior(.horizontalOnly)      // keep an item in the horizontal bar

Use .horizontalOnly for an item that switches between a symbol and text, such as a Select button that becomes Done, so it does not jump between axes. The system Edit button already does this.

// UIKit
item.axisBehavior = .verticalPreferred

Adapting custom views

A custom view you opt into the vertical bar must fit the bar’s fixed width or have its own vertical layout. Vertical bars have a fixed width and flexible item height, the reverse of horizontal bars. To adapt, read the edge, which is set when items can sit on the vertical axis and is nil or unspecified when they cannot:

@Environment(\.toolbarVerticalEdge) private var edge
// UIKit
switch traitCollection.verticalBarEdge { … }

Apple’s content advice is to prefer symbol-only items and to minimise text-only items and custom views that show both text and a symbol. A count shown as text next to an inbox symbol, for example, can become a badge on a symbol-only item. Text that carries real information, such as a cart total, belongs in the horizontal bar.

A few defaults that catch custom views out:

Opting out

Not every screen benefits. Apple names single-page layouts with heavy bottom content, such as a calculator, and sheets with only a close button:

.toolbarVerticalBehavior(.disabled)
// UIKit
override var preferredVerticalBarBehavior: UIVerticalBarBehavior { .disabled }

Opt out deliberately, per screen — not globally to avoid doing the work.

How to verify

Audit every screen’s bar on the closed outer display first, then on the inner display in landscape, and confirm it returns to horizontal in portrait. Check that labels are readable, that custom views are not clipped, and that the items you consider essential are visible rather than buried in overflow.

Applies to

← All checksFree evaluation