iOS Development
Navigation Bar
UI Design
Swift Programming
Mobile App Design

Change the color of iOS Navigation Bar

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Changing the color of an iOS navigation bar depends on which appearance API you are using. In modern UIKit, the most reliable approach is UINavigationBarAppearance, because it lets you configure the standard, compact, and scroll-edge appearances consistently.

The Modern UIKit Approach

For recent iOS versions, start with UINavigationBarAppearance:

swift
1import UIKit
2
3final class HomeViewController: UIViewController {
4    override func viewDidLoad() {
5        super.viewDidLoad()
6
7        let appearance = UINavigationBarAppearance()
8        appearance.configureWithOpaqueBackground()
9        appearance.backgroundColor = .systemBlue
10        appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
11        appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
12
13        navigationController?.navigationBar.standardAppearance = appearance
14        navigationController?.navigationBar.scrollEdgeAppearance = appearance
15        navigationController?.navigationBar.compactAppearance = appearance
16        navigationController?.navigationBar.tintColor = .white
17    }
18}

This changes:

  • The bar background color
  • The title color
  • The large-title color
  • The bar button item color through tintColor

Why scrollEdgeAppearance Matters

Many developers change only standardAppearance and then wonder why the navigation bar looks different when a scroll view reaches the top. On modern iOS versions, the scroll-edge appearance is a separate state.

If you want the bar to look the same in both situations, assign the same appearance object to both properties.

Global Styling with the Appearance Proxy

If you want the same color across the whole app, configure it once:

swift
1import UIKit
2
3@main
4class AppDelegate: UIResponder, UIApplicationDelegate {
5    func application(
6        _ application: UIApplication,
7        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
8    ) -> Bool {
9        let appearance = UINavigationBarAppearance()
10        appearance.configureWithOpaqueBackground()
11        appearance.backgroundColor = .black
12        appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
13        appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
14
15        UINavigationBar.appearance().standardAppearance = appearance
16        UINavigationBar.appearance().scrollEdgeAppearance = appearance
17        UINavigationBar.appearance().compactAppearance = appearance
18        UINavigationBar.appearance().tintColor = .white
19
20        return true
21    }
22}

This is useful for apps with a single brand theme.

Older Property-Based Styling

Older code often uses barTintColor and titleTextAttributes directly:

swift
1navigationController?.navigationBar.barTintColor = .systemGreen
2navigationController?.navigationBar.tintColor = .white
3navigationController?.navigationBar.titleTextAttributes = [
4    .foregroundColor: UIColor.white
5]

That style still appears in older projects, but UINavigationBarAppearance is the cleaner long-term API because it handles more states explicitly.

If you are working inside an older codebase, this explains why a small color tweak sometimes behaves differently across screens. The project may still have legacy bar configuration in one controller and appearance-based configuration in another.

Keep Contrast in Mind

The bar color is only half the job. Make sure:

  • Title text is readable
  • Bar button items have enough contrast
  • Large titles still match the same color system

A dark background with a dark tint color is a common mistake that makes the back button or title appear to vanish.

The same goes for translucent styles. If the bar is meant to be solid, use configureWithOpaqueBackground() so the final color does not unexpectedly blend with scrolled content underneath it.

Common Pitfalls

  • Updating only standardAppearance and forgetting scrollEdgeAppearance.
  • Setting the background color but not the text and button colors.
  • Mixing old barTintColor code with new appearance objects and getting inconsistent results.
  • Applying global styling when only one screen should be customized.

Summary

  • Use UINavigationBarAppearance for modern navigation bar color changes.
  • Set standard, compact, and scroll-edge appearances if you want consistent styling.
  • Update tintColor and text attributes along with the background color.
  • Use the appearance proxy for app-wide theming and direct controller configuration for screen-specific styling.
  • Most navigation-bar color bugs come from styling only one appearance state instead of all relevant ones.

When the result still looks wrong, check which controller owns the navigation stack before changing more colors. That often reveals the real source of the appearance override.


Course illustration
Course illustration

All Rights Reserved.