Z Index in SwiftUI : Setting things in order.

DevTechie Inc
Jan 15, 2023

ZIndex is used to alter default overlapping order in layout views. View with higher zIndex value appears at the top. Default value for zIndex is zero.

When two views overlap, framework determines the order by zIndex value and if two values are same, views are placed in the order they appear in hierarchy.

Let’s start with an example.

struct DevTechieZindexExample: View {
    
    var body: some View {
        VStack(spacing: 50) {
            Text("DevTechie.com")
                .font(.largeTitle)
            ZStack {
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.mint.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 20, y: 20)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.orange.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: -20, y: -20)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.indigo.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 10, y: -40)
            }
        }
    }
}
At this point, we don’t have any zIndex defined so mint color is covered by orange and indigo colors. Let’s add zIndex for each but give mint a higher value.

struct DevTechieZindexExample: View {
    
    var body: some View {
        VStack(spacing: 50) {
            Text("DevTechie.com")
                .font(.largeTitle)
            ZStack {
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.mint.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 20, y: 20)
                    .zIndex(1)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.orange.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: -20, y: -20)
                    .zIndex(0)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.indigo.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 10, y: -40)
                    .zIndex(0)
            }
        }
    }
}
Let’s update our view logic so we can dynamically change the zIndex for each of the rounded rect views. We will add three State variables and bind them to a Slider. We will use this Slider bound value as zIndex for RoundedRectangle view.

struct DevTechieZindexExample: View {
    @State private var idxMint = 0.0
    @State private var idxOrange = 0.0
    @State private var idxIndigo = 0.0
    
    var body: some View {
        VStack(spacing: 50) {
            Text("DevTechie.com")
                .font(.largeTitle)
            ZStack {
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.mint.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 20, y: 20)
                    .zIndex(idxMint)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.orange.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: -20, y: -20)
                    .zIndex(idxOrange)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.indigo.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 10, y: -40)
                    .zIndex(idxIndigo)
            }
            
            Slider(value: $idxMint, in: 0...10, step: 1.0) {
                Text("Mint zIndex")
            }
            
            Slider(value: $idxOrange, in: 0...10, step: 1.0) {
                Text("Orange zIndex")
            }
            
            Slider(value: $idxIndigo, in: 0...10, step: 1.0) {
                Text("Indigo zIndex")
            }
        }
        .padding()
    }
}
We saw example with ZStack but same is true for VStack as well. zIndex is applied on View so layout stack doesn’t matter. We can see that by changing our stack to VStack and updating offset values so views overlap.

struct DevTechieZindexExample: View {
    @State private var idxMint = 0.0
    @State private var idxOrange = 0.0
    @State private var idxIndigo = 0.0
    
    var body: some View {
        VStack(spacing: 50) {
            Text("DevTechie.com")
                .font(.largeTitle)
            VStack {
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.mint.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 50, y: 50)
                    .zIndex(idxMint)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.orange.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: -20, y: -20)
                    .zIndex(idxOrange)
                
                RoundedRectangle(cornerRadius: 20)
                    .fill(Color.indigo.gradient)
                    .frame(width: 100, height: 100)
                    .offset(x: 40, y: -60)
                    .zIndex(idxIndigo)
            }
            
            Slider(value: $idxMint, in: 0...10, step: 1.0) {
                Text("Mint zIndex")
            }
            
            Slider(value: $idxOrange, in: 0...10, step: 1.0) {
                Text("Orange zIndex")
            }
            
            Slider(value: $idxIndigo, in: 0...10, step: 1.0) {
                Text("Indigo zIndex")
            }
        }
        .padding()
    }
}



With that we have reached the end of this article. Thank you once again for reading. Don’t forget to follow 😍. Also subscribe our newsletter at https://www.devtechie.com