✨ Fix Clipping Issues in SwiftUI ScrollView

Get weekly handpicked updates on Swift and SwiftUI!

TL;DR: Prevent clipping in ScrollView by using scrollClipDisabled(true) on iOS 17+ or leveraging Introspect to set clipsToBounds = false on older iOS versions.

Problem

In SwiftUI, ScrollView clips content that exceeds its boundaries in the non-scrollable direction by default. How can we disable this behavior?

Solutions

1. Use scrollClipDisabled (iOS 17+)

Starting with iOS 17, SwiftUI provides the scrollClipDisabled modifier. Setting this to true prevents ScrollView from clipping content that extends beyond its boundaries.

Swift
struct ScrollClipDisableDemo: View {
    @State private var disable = true
    var body: some View {
        VStack {
            Toggle("Clip Disable", isOn: $disable)
                .padding(20)
            ScrollView {
                ForEach(0 ..< 10) { i in
                    Rectangle()
                        .fill(.blue)
                        .frame(height: 100)
                        .shadow(color: .black, radius: 50)
                        .overlay(Text("\(i)").foregroundColor(.white))
                }
            }
        }
        .scrollClipDisabled(disable)
    }
}

scrollClipDisabled

This will ensure that shadows, effects, or other content extending beyond the bounds of ScrollView are visible.

2. Use Introspect for Older iOS Versions

Introspect is a third-party library that allows access to underlying UIKit objects. On older iOS versions, you can modify the clipsToBounds property of the UIScrollView to disable clipping.

Swift
import Introspect

struct ScrollClipDisableDemo: View {
    @State private var disable = true
    var body: some View {
        VStack {
            Toggle("Clip Disable", isOn: $disable)
                .padding(20)
            ScrollView {
                ForEach(0 ..< 10) { i in
                    Rectangle()
                        .fill(.red)
                        .frame(height: 100)
                        .shadow(color: .black, radius: 50)
                        .overlay(Text("\(i)").foregroundColor(.white))
                }
            }
            .introspect(.scrollView, on: .iOS(.v16, .v17, .v18)) { scrollView in
                scrollView.clipsToBounds = !disable
            }
        }
        .frame(width: 100)
    }
}

This approach ensures compatibility with older versions of iOS where scrollClipDisabled is not available.

Additional Resources