Celebrating 200 Daily Coding Tips 🎉 all tutorials will be free to all this week!
The temptation with VStack or HStack is to use a Spacer to push content around. A Spacer expands to fill all available space, making it perfect for moving views to the right position within their layout container. Want to push content to the top? Put it in a VStack with a Spacer below it. Want to push it to the right? Put it in an HStack with a Spacer on the left.
But what if I told you that you don’t need a VStack or an HStack in these situations?
My first example aims to centre a Text that displays the UK English word centred. I’m providing ContentView, which has no Spacer, and ContentViewWithSpacers which has two. Both have a maxWidth of .infinity, because otherwise they would only be the width of the Text.
I want them to take up as much space as possible, because I’m displaying them in ContentView_Previews in a VStack.
Both of these give the Text a black background and white font colour, and I couldn’t resist rounding the corners with .cornerRadius as well. The main reason I added a background was to make the point that backgrounds are frozen in time. What do I mean by that? My background is added after the padding, making the background only slightly larger than the Text. If I increase the size of the frame after adding a background, the background remains at the same size it was.
For a long time I’ve placed views inside a Group to which I've added .frame(maxWidth: .infinity, maxHeight: .infinity). This gives me a container that can be given its own background, while leaving the view it contains intact.
This is actually not necessary, because every view can be seen as having the opportunity to create unlimited frames.
Here’s how it ends up looking:
As you can see, the two views look identical except for their background colour.
The view at the bottom has managed to add padding and a background to the Text, expand its frame, and then add the red background afterwards. You might notice that I haven’t specified an alignment either. Specifying alignment: .center is redundant, because the default value for the alignment parameter is already .center.
If I add alignment: .leading to the VStack of the blue ContentViewWithSpacers, it will behave the same way as if I add that alignment to ContentView before the red background is added.
There is no need for a ZStack to place the background behind the Text in ContentView, even though it was already given a background once.
But what if I add an alignment of .bottomTrailing?
This is where Spacer starts to create problems.
ContentView is free to lay a view out anywhere on the screen, because there are no other views that are resisting compression. But ContentViewWithSpacers requires that I remember to remove a Spacer. When I do that, I can actually use an alignment of .trailing, because the Text is already being shoved to the bottom by the remaining Spacer above it.
This is how using Spacer will actually complicate your layout, because alignments don’t actually mean what you expect them to mean.



