Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

Win a copy of The macOS App Icon Book with thisfree giveaway

ScrollView Bounce Behavior configuration in SwiftUI

A ScrollView bounce behavior configuration allows you to define whether a scrollable view bounces when reaching the end of its content. Whether it’s a horizontal or vertical scrolling list, you can configure both directions using view modifiers in SwiftUI.

There are common scenarios for us to build when it comes down to lists. You might want to disable bouncing completely or only enable it when the size of the inner content becomes larger than its parent list bounds. Let’s dive in!

How to enable ScrollView Bounce

SwiftUI enables ScrollView bounce by default when you generate a plain scrolling view:

ScrollView {
    Text("Small Content")
}

However, you can explicitly enable bouncing using the scrollBounceBehavior(_:axes:) modifier:

ScrollView {
    Text("Small Content")
}.scrollBounceBehavior(.always)

The above code example creates a ScrollView that will bounce in any direction, no matter the size of its content. Note that the same modifier applies to a List, Table, or TextEditor SwiftUI view.

How to disable vertical ScrollView bounce

You might want to disable horizontal or vertical ScrollView bounce in all cases. Unfortunately, there’s currently no better way than to use the appearance API for disabling:

/// Not recommended as it disables bounces for all your app's ScrollViews.
UIScrollView.appearance().bounces = false

However, this will turn it off for all your ScrollViews, which is not recommended. It’s important to understand that bouncing has a purpose: it naturally tells your users they’ve reached the end of the view. It’s best practice only to disable it if the content is small enough not even to be scrollable. In other words, the ScrollView feels like a non-scrollable view to the user so that the user won’t expect a bouncing behavior.

Stay updated with the latest in SwiftUI

The 2nd largest newsletter in the Apple development community with 19,200 developers. Don't miss out – Join today:

You can always unsubscribe, no hard feelings.

Disabling ScrollView bounce based on the content size

I recommend configuring your ScrollView bouncing behavior based on the size of its contents. Doing so brings the best of both worlds and ensures a user experience without confusion.

In the following code example, I’ve created a view with a orange bounding box to illustrate the size of our content:

struct ContentView: View {
    var body: some View {
        ScrollView {
            Group {
                Text("Small")
                Text("Content")
            }.background(Color.orange)
        }
        .scrollBounceBehavior(.always)
        .frame(maxHeight: .infinity)
    }
}

When running this view in the Simulator, you’ll notice that it doesn’t make sense for this view to be scrollable:

A ScrollView Bounce Behavior set to always doesn’t make sense for every view.

In this case, the size of the ScrollView’s content is small enough not to require scrolling. Therefore, we can configure the scroll bounce behavior to be based on the size:

ScrollView {
    Group {
        Text("Small")
        Text("Content")
    }.background(Color.orange)
}
 // Only enable scrolling when the content is large enough.
.scrollBounceBehavior(.basedOnSize)
.frame(maxHeight: .infinity)

You’ve now disabled the ScrollView bounce based on the content size, which will enable it when the user is required to scroll to see the whole inner content.

Understanding bounce behavior’s environment configuration

The scroll bounce behavior modifier uses the Environment for its configuration. This means that an outer view can configure the bounce behavior of an inner view:

VStack {
    ScrollView {
        Group {
            Text("Small")
            Text("Content")
        }.background(Color.orange)
    }
}
/// Even though we configure the bounce behavior on the outer VStack,
/// the inner ScrollView will still respond to this setting and only enable
/// scrolling when the size of its content requires so.
.scrollBounceBehavior(.basedOnSize)
.frame(maxHeight: .infinity)

Even though we’ve configured the scroll behavior using the outer VStack component, we still affect the inner ScrollView behavior.

Configuring ScrollView bounce for a specific axis

Finally, you can configure the ScrollView bounce behavior for a specific axis. In case you only want to affect horizontal scrolling views, you can use the following code:

.scrollBounceBehavior(.basedOnSize, axes: .horizontal)

The axes argument allows you to pass either vertical or horizontal.

Conclusion

ScrollView bounce behavior in SwiftUI can be configured to have the best outcome for the user’s expectation. Ideally, you would enable bouncing based on the size of the inner contents, as bouncing helps the user understand they reached the end of your view.

If you want to improve your SwiftUI knowledge, even more, check out the SwiftUI category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.

Thanks!