Contents

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 = .systemRed

In 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.

  1. Open the project’s storyboard file.

  2. Select the UINavigationBar from your UINavigationController scene.

  3. In the Attributes Inspector pane turn on these Appearances: “Standard”, “Compact”, “Scroll Edge”, and “Compact Scroll Edge”.

  4. For all four appearances, set the “Background” to “System Red Color”, for example.

Change the color of the title and button elements:

  1. Change the bar button items color: set the View’s “Tint” color to “White Color”.

  2. Change the Standard Text Attributes “Title” from “Inherited” to “Custom”.

  3. 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