BS
BleepingSwift
Published on
4 min read
Beginner

> Leading-Aligned Navigation Titles in UIKit with titleAlignment

Share:

For most of UIKit's history, the inline navigation title has sat in the center, and if you wanted it somewhere else you had to replace it with a custom titleView and fake the rest. The iOS 27.2 SDK finally adds a real API for it. UINavigationItem.titleAlignment lets you ask for a leading-aligned title, and a matching trait tells custom title views which alignment the bar actually used.

Setting the Alignment

The property takes a UINavigationItem.TitleAlignment value, and like everything else on the navigation item, you set it on the view controller that owns the title:

Swift
import UIKit

final class InboxViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Inbox"

        if #available(iOS 27.2, *) {
            navigationItem.titleAlignment = .leading
        }
    }
}

The availability check matters if your deployment target is anything below 27.2, which it almost certainly is today. On older versions the title just stays where it always was.

What Each Option Does

There are three cases, and the header comments in the SDK are more specific about them than you might expect.

.automatic is the default, and it means the system decides. The title is usually centered, but UIKit may lead-align it depending on the context the bar is rendered in. The navigation item's style is one of the inputs to that decision.

.leading puts the title at the leading edge, which means the right side in right-to-left languages.

.center is stricter than it sounds. It never falls back to leading alignment the way .automatic can. When a long title can't fit centered, the bar slides it toward the leading edge to clear whatever buttons sit on the trailing side, and it only starts truncating once it has nowhere left to slide. If you have a screen where a centered title matters for your design, .center is the way to guarantee it.

Swift
final class SettingsViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Notification Settings"

        if #available(iOS 27.2, *) {
            navigationItem.titleAlignment = .center
        }
    }
}

Matching the Alignment in a Custom Title View

If you use navigationItem.titleView for something like a two-line title, you need to know which alignment the bar settled on so your content lines up with it. That's the job of the new navigationTitleAlignment trait. It reports .leading or .center once the bar has resolved an alignment, and .automatic if it hasn't resolved one yet.

Register for changes to UITraitNavigationTitleAlignment and update your layout whenever it changes:

Swift
@available(iOS 27.2, *)
final class MailboxTitleView: UIView {
    private let titleLabel = UILabel()
    private let subtitleLabel = UILabel()
    private let stack = UIStackView()

    init(title: String, subtitle: String) {
        super.init(frame: .zero)

        titleLabel.text = title
        titleLabel.font = .preferredFont(forTextStyle: .headline)
        subtitleLabel.text = subtitle
        subtitleLabel.font = .preferredFont(forTextStyle: .caption1)
        subtitleLabel.textColor = .secondaryLabel

        stack.axis = .vertical
        stack.addArrangedSubview(titleLabel)
        stack.addArrangedSubview(subtitleLabel)
        stack.translatesAutoresizingMaskIntoConstraints = false
        addSubview(stack)

        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: topAnchor),
            stack.bottomAnchor.constraint(equalTo: bottomAnchor),
            stack.leadingAnchor.constraint(equalTo: leadingAnchor),
            stack.trailingAnchor.constraint(equalTo: trailingAnchor),
        ])

        registerForTraitChanges([UITraitNavigationTitleAlignment.self]) { (view: MailboxTitleView, _) in
            view.updateAlignment()
        }
        updateAlignment()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func updateAlignment() {
        switch traitCollection.navigationTitleAlignment {
        case .leading:
            stack.alignment = .leading
        default:
            stack.alignment = .center
        }
    }
}

Then install it and set the alignment you want on the navigation item:

Swift
@available(iOS 27.2, *)
final class MailboxViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.titleView = MailboxTitleView(title: "Inbox", subtitle: "12 unread")
        navigationItem.titleAlignment = .leading
    }
}

Apple's header has two rules worth keeping in mind here. Use the trait to position content inside the size your view already reports, not to change that size, which is why the example only changes the stack's alignment. And overriding the trait yourself through traitOverrides won't move the title. The navigation item's titleAlignment is the only thing that controls the bar.

What About SwiftUI?

There's no SwiftUI equivalent yet. I searched the SwiftUI interfaces in the iOS 27.2 beta SDK and didn't find a title alignment modifier, so for now this is a UIKit feature. The property is also iOS, iPadOS, and Mac Catalyst only. It isn't available on tvOS or visionOS.

It's a small API, but it removes a common reason to build a custom title view, and the .center behavior makes centered titles predictable when trailing buttons get crowded. If you already ship a fake leading title, it's worth swapping it for the real thing once you can require iOS 27.2.

Sample Project

Want to see this code in action? Check out the complete sample project on GitHub:

View on GitHub

The repository includes a working Xcode project with all the examples from this article, plus unit tests you can run to verify the behavior.

subscribe.sh

// Stay Updated

Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.

>

By subscribing, you agree to our Privacy Policy.