DEV Community

MZ
MZ

Posted on

TextField Background Behaviour in SwiftUI

Technical Notes

TextField background

Let's say you have this code:

VStack {
    VStack {
        TextField("type in a todo", text: $textfieldInput)
          .background(.red)
    }
}
Enter fullscreen mode Exit fullscreen mode

In your simulator, or when you run this, TextField will be pushed all the way to the end of the screen (just below the safe area) but its background will include the safe area. Essentially, it would look as if you had a red navigation bar.

This is one of the quirks and technicalities of how SwiftUI handles this.

TextField in SwiftUI does not have boundaries by default. It only has the height of its text. That height is considered its "boundary".
So when you have a TextField pushed up against the top of the screen, SwiftUI sees that and says "Okay, I will push you all the way into the safe area.". Hence why you see the TextField's "boundary" include the safe area.

Couple of things to do, to fix this, and to note, about TextField's behaviour here or the way we attach modifiers to it.

VStack {
    VStack {
        TextField("type in a todo", text: $textfieldInput)
            .padding()
    }
}
Enter fullscreen mode Exit fullscreen mode

When we apply the .padding() modifier, this applies an inner padding to the TextField. What this means is, you will have a bigger tap area and a bigger space for your text inside the TextField to breathe and to be tapped. For clarity, this isn't outer padding. This is the padding inside.

Now, with this small change, your TextField now has a "boundary". Re-run the code, and possibly apply a .background() modifier, and you will see that the TextField now behaves as expected. There are no more unwanted background spillage.

SwiftUI just needs you to express a boundary for your TextField.

Now, you can apply 2 paddings to TextField. One for the inner room for the text to breathe and to make a sizeable tappable space and the other for its actual outer padding.

VStack {
    VStack {
        TextField("type in a todo", text: $textfieldInput)
            .padding()
            .background(.red)
            .cornerRadius(10)
            .padding()
    }
}
Enter fullscreen mode Exit fullscreen mode

Also, as a bonus, another way of making sure TextField behaves correctly is to apply the .padding() modifier to the inner VStack itself. This signifies to SwiftUI that the inner VStack has a boundary, so it would "push" the VStack away from the safe area.

Top comments (0)