iOS 27: UIBarMinimization
Control navigation bar during scroll in UIKit
Apple added one of those small UIKit APIs that can remove a surprising amount of custom scroll handling.
In iOS 27, a navigation bar can minimize in response to scrolling, restore independently, and decide whether the safe area should change during the transition. The configuration is exposed through UIBarMinimization and attached to a UINavigationItem.
This feature is still in beta and might change before the final release. Warning you as usual.
What It Does
UIBarMinimization is a configuration object that controls how a navigation bar reacts to scrolling.
It has three instance properties:
minimizationBehaviorrestorationBehaviorsafeAreaAdjustment
That separation is useful because minimizing the bar, restoring it, and reflowing the content are three different decisions.
Basic UIKit Example
final class ArticlesViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "Articles"
let minimization = UIBarMinimization()
minimization.minimizationBehavior = .onScrollDown
minimization.restorationBehavior = .automatic
minimization.safeAreaAdjustment = .automatic
navigationItem.navigationBarMinimization = minimization
}
}When the user scrolls down, UIKit minimizes the navigation bar. The system owns the animation and coordinates it with the table view.
There is no need to observe contentOffset, calculate progress manually, or animate the navigation bar yourself.
minimizationBehavior
minimizationBehavior controls when the navigation bar starts minimizing.
Its type is UIBarMinimizationBehavior.
.automatic
minimization.minimizationBehavior = .automaticThe system determines the appropriate minimization behavior for the current context.
This is the safest default when the screen does not require a particular scroll direction.
.never
minimization.minimizationBehavior = .neverDisables navigation bar minimization.
Use it when navigation controls need to remain visible at all times or when minimizing would make the interface feel unstable.
.onScrollDown
minimization.minimizationBehavior = .onScrollDownThe navigation bar minimizes when the user scrolls down through the content.
This is a natural fit for article readers, feeds, documentation, and other top-to-bottom content.
.onScrollUp
minimization.minimizationBehavior = .onScrollUpThe navigation bar minimizes when the user scrolls upward.
This is more suitable for bottom-aligned content, such as some chat or timeline layouts.
restorationBehavior
restorationBehavior controls when a minimized navigation bar expands again.
Its type is UIBarMinimizationRestorationBehavior.
This is separate from minimizationBehavior. For example, a bar can minimize immediately when scrolling starts but remain minimized until the content reaches an edge.
.automatic
minimization.restorationBehavior = .automaticThe system chooses the restoration behavior.
In the standard interaction, the bar can restore when the user reverses the scroll direction.
.atScrollEdge
minimization.restorationBehavior = .atScrollEdgeThe bar remains minimized until the scroll view reaches the relevant content edge.
This is useful when the navigation bar is mostly interface chrome and does not need to reappear every time the user slightly changes direction.
It can make long reading or browsing screens feel calmer because small scroll reversals do not continuously expand and collapse the bar.
safeAreaAdjustment
safeAreaAdjustment controls whether the safe area changes while the navigation bar minimizes.
Its type is UIBarMinimizationSafeAreaAdjustment.
.automatic
minimization.safeAreaAdjustment = .automaticThe system determines whether the safe area should adjust.
This should be the starting point for most screens.
.enabled
minimization.safeAreaAdjustment = .enabledThe safe area changes together with the navigation bar, allowing the content to reflow into the newly available space.
This works well for regular scrolling content such as lists, articles, and documentation.
.disabled
minimization.safeAreaAdjustment = .disabledThe safe area remains unchanged while the navigation bar minimizes.
The bar still animates, but the content layout does not expand into the released area.
This can be useful for full-screen media, custom layouts, or screens that already manage their own content insets.
Complete Example
import SwiftUI
import UIKit
final class ArticlesViewController: UITableViewController {
private struct Article {
let title: String
let summary: String
let category: String
}
private let articles: [Article] = [
Article(
title: "Designing for Liquid Glass",
summary: "Explore depth, material layering, and responsive controls in modern UIKit interfaces.",
category: "Design"
),
.....
]
override func viewDidLoad() {
super.viewDidLoad()
title = "Articles"
view.backgroundColor = .systemBackground
tableView.register(UITableViewCell.self, forCellReuseIdentifier: ArticleCell.reuseIdentifier)
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 96
var minimization = UIBarMinimization()
minimization.minimizationBehavior = .onScrollDown
minimization.restorationBehavior = .automatic
minimization.safeAreaAdjustment = .automatic
navigationItem.navigationBarMinimization = minimization
}
override func numberOfSections(in tableView: UITableView) -> Int {
1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
articles.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ArticleCell.reuseIdentifier, for: indexPath)
let article = articles[indexPath.row]
var content = UIListContentConfiguration.subtitleCell()
content.text = article.title
content.secondaryText = "\(article.category) - \(article.summary)"
content.textProperties.font = .preferredFont(forTextStyle: .headline)
content.secondaryTextProperties.font = .preferredFont(forTextStyle: .subheadline)
content.secondaryTextProperties.color = .secondaryLabel
content.textToSecondaryTextVerticalPadding = 6
cell.contentConfiguration = content
cell.accessoryType = .disclosureIndicator
return cell
}
}
private enum ArticleCell {
static let reuseIdentifier = "ArticleCell"
}
private struct ArticlesPreview: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UINavigationController {
UINavigationController(rootViewController: ArticlesViewController())
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
}
}
#Preview {
ArticlesPreview()
}This configuration minimizes the navigation bar while scrolling down, keeps it minimized during small direction changes, and restores it when the content reaches the scroll edge.
The safe area also adjusts, so the table view can use the extra vertical space.
Visually it looks like this for .onScrollDown
and .onScrollUp
What About SwiftUI
There is a new Beta toolbarMinimizationBehavior(_:for:) with available parameters:
.automatic.never.onScrollDown.onScrollUp
The system still owns the animation and transition. We only choose when minimization is allowed.
Basic SwiftUI Example
NavigationStack {
ScrollView {
LazyVStack(spacing: 16) {
ForEach(0..<50) { index in
Text(”Item \(index)”)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
}
.padding()
}
.navigationTitle(”Articles”)
.toolbarMinimizationBehavior(
.onScrollDown,
for: .navigationBar
)
}Why the Three Properties Matter
A custom collapsing navigation bar often combines everything into one scroll-offset calculation:
when the bar disappears
when it comes back
how the content moves underneath it
UIBarMinimization separates those concerns.
That makes it possible to create combinations such as:
let minimization = UIBarMinimization()
minimization.minimizationBehavior = .onScrollDown
minimization.restorationBehavior = .atScrollEdge
minimization.safeAreaAdjustment = .disabled
navigationItem.navigationBarMinimization = minimizationHere, the navigation bar minimizes while scrolling down and stays minimized until the edge is reached, but the content keeps its original safe area throughout the transition.
Where It Fits
This behavior makes sense for screens where vertical space matters:
article readers
documentation
news feeds
long settings screens
mail and message lists
I would avoid enabling it everywhere. A short form or a screen with only a few controls probably gains little from a navigation bar that keeps moving.
It is also worth testing screens that use search, integrated top tabs, custom content insets, overlays, or custom toolbar items. UIKit handles the bar animation, but the surrounding layout can still affect the final result.
References
Apple Developer Documentation: UIBarMinimization
Apple Developer Documentation: UIBarMinimizationBehavior
Apple Developer Documentation: UIBarMinimizationRestorationBehavior
Apple Developer Documentation: UIBarMinimizationSafeAreaAdjustment
Apple Developer Documentation: UINavigationItem.navigationBarMinimization
Apple Developer Documentation: toolbarMinimizationBehavior
WWDC26 Session: Modernize your UIKit app
