Making SwiftUI shadows not bleed in sibling views

Viewed 246

SwiftUI shadows are overlapping into other inner sibling views:

shadows overlapping

Is there a way to fix this and get a proper shadow in that case?

Example view:

// SwiftUIPlayground
// https://github.com/ralfebert/SwiftUIPlayground/

import SwiftUI

struct ShadowsView: View {
    var body: some View {
        Color.yellow
            .ignoresSafeArea()
            .overlay(self.scrollView, alignment: .bottom)
    }

    var scrollView: some View {
        VStack {
            ForEach(1 ... 3, id: \.self) { _ in
                Color.white
                    .frame(height: 100)
                    .cornerRadius(10)
                    .shadow(color: Color.red, radius: 30, x: 0, y: 0)
            }
        }
        .padding()
        .frame(height: 200, alignment: .top)
    }
}
1 Answers

You can use .compositingGroup() and then apply the shadow.

The documentation states:

A compositing group makes compositing effects in this view’s ancestor views, such as opacity and the blend mode, take effect before this view is rendered.

This means that the views are all composited together with the shadows done separately, rather than the shadow being effected by the views underneath it.

Code:

VStack {
    ForEach(1 ... 3, id: \.self) { _ in
        Color.white
            .frame(height: 100)
            .cornerRadius(10)
            // .shadow(color: Color.red, radius: 30, x: 0, y: 0)  // <- REMOVED
    }
}
.compositingGroup()  // <- ADDED
.shadow(color: Color.red, radius: 30, x: 0, y: 0)  // <- ADDED
.padding()
.frame(height: 200, alignment: .top)

Result:

Result

Related