TN3106: Customizing the appearance of UINavigationBar
Adopt UINavigationBarAppearance for a navigation bar background color that’s consistent on iOS 13 through 18.
Overview
UINavigationBar in iOS 15 introduces changes to its appearance settings. It extends the usage of its scrollEdgeAppearance, which by default produces a transparent background, to all navigation bar styles.
The iOS 13 SDK introduced an appearance settings class UINavigationBarAppearance. If you’re seeing a view controller with appearance issues like a black navigation bar or incorrect status bar content color when building with Xcode 13 and running on iOS 15, adopt UINavigationBarAppearance. For a view controller that scrolls its content, use it to apply both standardAppearance and scrollEdgeAppearance to the UINavigationBar.
Configure the UINavigationBarAppearance
Consider an app that uses UITableViewController, and has the following code in application(_ :didFinishLaunchingWithOptions:):
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().barTintColor = .systemRedIn iOS 14.x or later, the navigation bar color turns transparent (showing the black background underneath), yet iOS 13 draws the navigation bar in .systemRed.
To standardize the navigation bar’s appearance between these versions of iOS, use the UINavigationBarAppearance API. Use the following example to apply an opaque navigation bar colored .systemRed with white title text. Setting the text color here is only an example and of course is optional.
@available(iOS 13.0, *)
func customNavBarAppearance() -> UINavigationBarAppearance {
let customNavBarAppearance = UINavigationBarAppearance()
// Apply a red background.
customNavBarAppearance.configureWithOpaqueBackground()
customNavBarAppearance.backgroundColor = .systemRed
// Apply white colored normal and large titles.
customNavBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
customNavBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
// Apply white color to all the nav bar buttons.
let barButtonItemAppearance = UIBarButtonItemAppearance(style: .plain)
barButtonItemAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.white]
barButtonItemAppearance.disabled.titleTextAttributes = [.foregroundColor: UIColor.lightText]
barButtonItemAppearance.highlighted.titleTextAttributes = [.foregroundColor: UIColor.label]
barButtonItemAppearance.focused.titleTextAttributes = [.foregroundColor: UIColor.white]
customNavBarAppearance.buttonAppearance = barButtonItemAppearance
customNavBarAppearance.backButtonAppearance = barButtonItemAppearance
customNavBarAppearance.doneButtonAppearance = barButtonItemAppearance
return customNavBarAppearance
}Configure the entire app
To apply this appearance to the navigation bar throughout the entire app:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let newNavBarAppearance = customNavBarAppearance()
let appearance = UINavigationBar.appearance()
appearance.scrollEdgeAppearance = newNavBarAppearance
appearance.compactAppearance = newNavBarAppearance
appearance.standardAppearance = newNavBarAppearance
if #available(iOS 15.0, *) {
appearance.compactScrollEdgeAppearance = newNavBarAppearance
}
return true
}Configure a view controller
To apply this appearance to the navigation bar of an individual view controller:
override func viewDidLoad() {
super.viewDidLoad()
let newNavBarAppearance = customNavBarAppearance()
navigationController!.navigationBar.scrollEdgeAppearance = newNavBarAppearance
navigationController!.navigationBar.compactAppearance = newNavBarAppearance
navigationController!.navigationBar.standardAppearance = newNavBarAppearance
if #available(iOS 15.0, *) {
navigationController!.navigationBar.compactScrollEdgeAppearance = newNavBarAppearance
}
}If you’re using storyboards, instead configure both the appearance of the navigation bar and the elements within that bar.
To change the appearance of the navigation bar:
Choose “standard” and “scroll edge appearances” for the navigation bar, by setting the appearance proxy of UINavigationBar: “Standard”, and “ScrollEdge” appearances.
Open the project’s storyboard file.
Select the
UINavigationBarfrom yourUINavigationControllerscene.In the Attributes Inspector pane turn on these Appearances: “Standard”, “Compact”, “Scroll Edge”, and “Compact Scroll Edge”.
For all four appearances, set the “Background” to “System Red Color”, for example.
Change the color of the title and button elements:
Change the bar button items color: set the View’s “Tint” color to “White Color”.
Change the Standard Text Attributes “Title” from “Inherited” to “Custom”.
Change the Standard Title Attributes “Title Color” from “Default” to “White Color”. Repeat steps 2 and 3 for: Scroll Edge and Compact Scroll Edge appearances.
Revision History
2025-09-03 Added information about the new design in iOS 26.
2022-03-01 First published.
See Also
Latest
TN3205: Low-latency communication with RDMA over ThunderboltTN3206: Updating Apple Pay certificatesTN3179: Understanding local network privacyTN3190: USB audio device design considerationsTN3194: Handling account deletions and revoking tokens for Sign in with AppleTN3193: Managing the on-device foundation model’s context windowTN3115: Bluetooth State Restoration app relaunch rulesTN3192: Migrating your iPad app from the deprecated UIRequiresFullScreen keyTN3151: Choosing the right networking APITN3111: iOS Wi-Fi API overviewTN3191: IMAP extensions supported by Mail for iOS, iPadOS, and visionOSTN3134: Network Extension provider deploymentTN3189: Managing Mail background traffic loadTN3187: Migrating to the UIKit scene-based life cycleTN3188: Troubleshooting In-App Purchases availability in the App Store