Swift
iOS Development
Navigation Bar
UI Customization
Mobile App Design

Changing navigation bar color in Swift

Master System Design with Codemia

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

Introduction

Changing a navigation bar color in Swift is easy, but the correct API depends on the iOS generation you target. Older code used barTintColor, tintColor, and titleTextAttributes directly on UINavigationBar. Modern iOS apps should usually configure a UINavigationBarAppearance, because it gives consistent results across standard, scroll-edge, and compact appearances.

The Modern iOS 13+ Approach

For current UIKit code, create a UINavigationBarAppearance and assign it to the navigation item or navigation bar.

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

This changes the bar background, title color, and button tint color in a way that survives modern appearance transitions.

What Each Property Affects

A navigation bar has several visual layers:

  • 'backgroundColor on the appearance controls the bar background'
  • 'tintColor controls bar button items and back indicators'
  • 'titleTextAttributes controls the title text'
  • 'largeTitleTextAttributes controls the large title style'

If you set only one of these, the bar may look partially customized rather than fully themed.

Apply It Globally If the App Uses One Theme

If the whole app should share one navigation style, configure the appearance proxy during app startup.

swift
1import UIKit
2
3func configureNavigationBarTheme() {
4    let appearance = UINavigationBarAppearance()
5    appearance.configureWithOpaqueBackground()
6    appearance.backgroundColor = .systemRed
7    appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
8    appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
9
10    let navBar = UINavigationBar.appearance()
11    navBar.tintColor = .white
12    navBar.standardAppearance = appearance
13    navBar.scrollEdgeAppearance = appearance
14    navBar.compactAppearance = appearance
15}

This keeps the styling centralized and avoids repeating the same code in every controller.

Per-Screen Overrides Still Work

If one screen needs a special navigation style, set its appearance in that view controller instead of using the global proxy. This is useful for onboarding flows, modal stacks, or branded feature areas that intentionally differ from the rest of the app. The key is to be explicit, because a per-screen override can otherwise appear to "fight" the app-wide theme.

Older barTintColor Code Still Appears

You will still see legacy examples like this:

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

That approach worked in older UIKit versions, but UINavigationBarAppearance is now the more reliable API, especially for large titles and scroll-edge behavior.

Dark Mode and Semantic Colors

If the app supports light and dark mode, prefer semantic colors or explicitly define both variants.

swift
appearance.backgroundColor = .systemBackground
navigationController?.navigationBar.tintColor = .label

Or provide your own named asset colors if the design requires a branded palette.

The important part is testing both themes. A bar that looks good in light mode can become unreadable in dark mode if title and tint colors are not set deliberately.

Common Pitfalls

  • Setting only tintColor and expecting the navigation bar background color to change.
  • Using old barTintColor examples in modern UIKit without configuring UINavigationBarAppearance.
  • Forgetting scrollEdgeAppearance, which makes the bar revert to a different style during scrolling.
  • Styling one view controller locally when the whole app really needs a centralized appearance configuration.
  • Choosing colors that reduce title or bar button contrast, especially in dark mode.

Summary

  • In modern Swift UIKit code, prefer UINavigationBarAppearance for navigation bar color changes.
  • Set the background color, title attributes, and tint color together for a complete theme.
  • Apply the appearance globally when the whole app shares one navigation style.
  • Legacy barTintColor code still exists, but it is not the best default for newer iOS versions.
  • Test the result with large titles, scroll-edge behavior, and dark mode enabled.

Course illustration
Course illustration

All Rights Reserved.