Background image scales incorrectly when ignoring safe area

In a SwiftUI project I try to display a background image with ignoring safe area insets (to make it go edge to edge). However, the background scales incorrectly and doesn't respect its aspect ratio.

Here is a small code example of the view structure that I'm using:

struct ContentView: View {
  var body: some View {
    ZStack {
      Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.").padding()
    }.frame(maxHeight: .infinity).background(Image("dots").resizable().ignoresSafeArea().scaledToFill())
  }
}

And an example image for testing (when using this image you can clearly see the circles become more like ovals in the SwiftUI app):

Screenshot:

Replies

The order of effects is important. This works:

struct ContentView: View {
	var body: some View {
		ZStack {
			Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.").padding()
		}
		.frame(maxHeight: .infinity)
		.background(Image("dots")
			.resizable()
			.scaledToFill()    // - These two were swapped around
			.ignoresSafeArea() // -
		)
	}
}

  • This works well for the scaling issue, but it makes the image go off-center. Is there any way to properly center it?

    Thanks!

Add a Comment

The scaling works nicely, but the image is not centered anymore (it moves a bit to the right). Do you know how to fix that as well? Thanks!

I think you may need to fiddle with the centre of the image?

It looks like it draws the image from the top left (0, 0), ignoring safe edges, and because the device is taller than it is wide (portrait) more of the image is moved off the right. To put it another way, you're using a square image on a rectangular device.

If your image is 1000px wide x 1000px high and your device is 500px wide x 1000px high, and the image is not centred, you'll see the left half of the image.

If it helps you align it, I've drawn a cross in the centre so you can see where it currently is.

I don't think adjusting the image would help, because the alignment would be different on other devices with different screen sizes. It does center correctly when it doesn't ignore the safe area, so something must be going wrong with that.

To illustrate the difference, here are 2 screenshots:

I had the same issue where my background would shift when I changed some of the content on top of it. I couldn't identify what the issue was but when coming back to the issue in iOS 16.4-6 I found that the shift was always present, not affected by the overlaid content anymore. Well I guess consistency is often easier to deal with!

I found another blog describing how to get a fullscreen background image and it gave me a clue that helped me solve the issue (though it doesn't actually go into this specific issue and you can actually see that earlier in the page it's affected by the issue as the moon is shifted to the right but ends up central): https://ix76y.medium.com/space-travel-app-part-1-creating-a-fullscreen-background-image-in-swiftui-beginner-tutorial-ca6f950b3b8

I was using .scaledToFill() like you but that seems to be part of the problem, if you instead use the following (as shown in the blog) it doesn't shift the image and looks like it scales ok:

.aspectRatio(contentMode: .fill)
.frame(minWidth: 0, maxWidth: .infinity)