swiftuiswiftui-navigationstack

Issue with Margin During Navigation Transition in iOS 18


The new .navigationTransition feature introduced in SwiftUI for iOS 18+ offers an impressive animated screen transition. However, during the transition, the parent view shrinks, leaving a white margin (or black in dark mode) around the edges.

image

If the background color of the parent view matches this margin color, it appears seamless. However, as shown in the attached example, when using a custom color or gradient background, the margin becomes visually disruptive.

Is there a way to address this?

import SwiftUI

struct ContentView: View {
    @Namespace var namespace
    var body: some View {
        NavigationStack {
            Form {
                NavigationLink {
                    ZStack {
                        Color.yellow.ignoresSafeArea()
                        Text("Detail View")
                    }
                    .navigationTitle("Transition")
                    .navigationTransition(.zoom(sourceID: "hellow", in: namespace))
                } label: {
                    Text("Open")
                        .font(.largeTitle)
                        .matchedTransitionSource(id: "hellow", in: namespace)
                }

            }
            .scrollContentBackground(.hidden)
            .background(Color.mint.ignoresSafeArea())
        }
    }
}

#Preview {
    ContentView()
}

Applying .ignoreSafeArea() to the background view doesn’t seem to resolve the issue, which suggests this margin might not be related to the safe area. Any insights or solutions would be greatly appreciated.


Solution

  • The space at the edges is being caused by a scaling effect being applied to the background. The background is being made smaller, so it no longer fills the frame.

    As a workaround, I would suggest adding some negative padding to the background. This way, the background starts off larger than the frame it is filling and remains larger than the frame, even after being scaled down.

    On an iPhone 16, increasing the size by -50 on all sides seems to do the trick:

    Form {
        // ...
    }
    .scrollContentBackground(.hidden)
    .background {
        Color.mint
            .padding(-50)
            .ignoresSafeArea()
    }
    

    Animation