Environment
- Xcode 27.1
- iOS 27.1
- iPhone Duo simulator
- UIKit app built with the iOS 27.1 SDK
Issue
On iPhone Duo, the background of a system-managed UINavigationBar does not extend completely to the top edge of the window.
The navigation bar is configured using UINavigationBarAppearance with an opaque blue background. However, a horizontal white strip remains above the blue navigation bar.
I also post a feedback: FB24859353
Questions
- Is this expected behavior on iPhone Duo?
- What is the recommended way to style this top region?
- Should apps add a custom background underlay outside the UINavigationBar bounds?
- Could this be an iOS 27.1 or iPhone Duo simulator issue?
Minimal reproduction code:
import UIKit
final class DemoTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
viewControllers = NavigationBarStyle.allCases.map { style in
let content = DiagnosticsViewController(style: style)
let navigationController = UINavigationController(rootViewController: content)
navigationController.tabBarItem = UITabBarItem(
title: style.title,
image: UIImage(systemName: style.symbolName),
selectedImage: nil
)
style.apply(to: navigationController.navigationBar)
return navigationController
}
}
}
enum NavigationBarStyle: CaseIterable {
case systemDefault
case appearance
case legacy
var title: String {
switch self {
case .systemDefault:
return "Default"
case .appearance:
return "Appearance"
case .legacy:
return "Legacy"
}
}
var symbolName: String {
switch self {
case .systemDefault:
return "iphone"
case .appearance:
return "paintbrush"
case .legacy:
return "clock.arrow.circlepath"
}
}
func apply(to navigationBar: UINavigationBar) {
switch self {
case .systemDefault:
break
case .appearance:
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = .demoBlue
appearance.shadowColor = nil
appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
navigationBar.tintColor = .white
navigationBar.standardAppearance = appearance
navigationBar.compactAppearance = appearance
navigationBar.scrollEdgeAppearance = appearance
case .legacy:
navigationBar.tintColor = .white
navigationBar.barTintColor = .demoBlue
navigationBar.backgroundColor = .demoBlue
navigationBar.setBackgroundImage(Self.solidImage(color: .demoBlue), for: .default)
navigationBar.shadowImage = UIImage()
navigationBar.isTranslucent = false
navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
}
}
private static func solidImage(color: UIColor) -> UIImage {
return UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { context in
color.setFill()
context.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
}
}
}
private extension UIColor {
static let demoBlue = UIColor(red: 0.0, green: 0.46, blue: 0.70, alpha: 1.0)
}
I would take a step back and look at this from the perspective of Adopting Liquid Glass. One important statement there is this:
Reduce your use of custom backgrounds in controls and navigation elements. Any custom backgrounds and appearances you use in these elements might overlay or interfere with Liquid Glass or other effects that the system provides, such as the scroll edge effect. Make sure to check any custom backgrounds in elements like split views, tab bars, and toolbars. Prefer to remove custom effects and let the system determine the background appearance, especially for the following elements: [...] UINavigationBar