Insetting Scrollable Views’ Content With contentMargins In SwiftUI

Posted in SwiftUI

September 20th, 2024

⏱ Reading Time: 4 mins

SwiftUI simplifies the way we build user interfaces across Apple platforms. It provides a large set of tools to use, such as built-in views and view modifiers, with the contentMargins modifier being among them. Introduced in iOS 17, it allows to inset content within scrollable views like ScrollViewList and TextEditor, resulting in cleaner layouts and a smoother user interface overall. This post shows how to use contentMargins modifier and demonstrates its effects, so read on to find out more.

Using the contentMargins view modifier

First and foremost, contentMargins view modifier creates space around content, just like padding does. But unlike to it, contentMargins does not apply to each individual view. Instead, it affects all views that exist as content in a scrollable view.

To see how it works, let’s consider for starters the following small SwiftUI view that presents a series of colors in a scrollview:

See that each color occupies all the available width in the scrollview. With contentMargins modifier we can change that easily, and create some spacing (margin) around each color view like so:

Notice that contentMargins is attached to the scrollview directly and not to its content views. In the above example, a margin of 40 points will be added around the entire content; top, bottom, leading, trailing.

It’s also possible to specify just one axis to add margins, by providing it as a first argument:

Even more, we can specify a single edge if needed:

Setting a placement

If you try any of the above out, you will notice that the scroll indicator follows the new positioning of the content, sticking always to its trailing edge:

We can override that default behavior by specifying a placement; the part of the view to inset. There are two values to choose from in addition to the automatic behavior that applies to all previous examples:

  • scrollContent
  • scrollIndicators

In the following configuration, contentMargins adds margin around the content only, leaving the scroll indicator to its original place in the trailing edge of the view. That’s mostly useful when presenting content in large screens, where adding margins improves the UI, but the scroll indicator (scrollbar) would be better to stick to its original position:

Of course, a specific placement and an edge (or axis) can exist together in the same call of contentMargins. For instance, the following will inset only the content horizontally, while the scroll indicator will remain in its original place:

The second option for placement regards the scroll indicator. With it, the actual content remains intact, but the scrollbar acquires spacing to either all or specific edges. In the next example, we set margins for the scroll indicator in the vertical axis only:

Note that contentMargins modifier can by applied conditionally, based, for example, on the device type or the size class. You may want to set margins when the app runs on iPad but not on iPhone, or set margins for regular size class and not for compact. For example:

Conclusion

Even though contentMargins view modifier is easy to use, you might need to get the hang of it at first until you realize how it affects content. Keep in mind that it works with scrollable views only and has overall effect to all contained views. And with no doubt, it’s a great tool to have in addition to padding in order to add spacing around our views.

Thank you for reading, take care!

Stay Up To Date

Subscribe to my newsletter and get notifiied instantly when I post something new on SerialCoder.dev.

    We respect your privacy. Unsubscribe at any time.