282

I'm beginning to try out SwiftUI and I'm surprised that it doesn't seem to be straightforward to change the background color of a View. How do you do this using SwiftUI?

jeremyabannister
  • 3,796
  • 3
  • 16
  • 25

20 Answers20

332

Screen's Background Color

(As of Xcode Version 13)

I'm not sure if the original poster meant the background color of the entire screen or of individual views. So I'll just add this answer which is to set the entire screen's background color.

Using ZStack

var body: some View {
    ZStack {
            Color.purple
                .ignoresSafeArea()
            
            // Your other content here
            // Other layers will respect the safe area edges
    }
}

I added .ignoresSafeArea() otherwise, it will stop at safe area margins.

Using Overlay Modifier

var body: some View {
    Color.purple
        .ignoresSafeArea(.vertical) // Ignore just for the color
        .overlay(
            VStack(spacing: 20) {
                Text("Overlay").font(.largeTitle)
                Text("Example").font(.title).foregroundColor(.white)
        })
}

Note: It's important to keep the .ignoresSafeArea on just the color so your main content isn't ignoring the safe area edges too.

iOS 15

iOS 15/Xcode 13 has introduced some changes to the way Styles work with the edges of safe areas.

From my observation, the rule is: If the style touches the safe area edge, it will bleed into the safe area.

This gives you more options for setting a background color/style.

What is a Style?

A Style can be:

  • Colors
  • Materials (blur effects)
  • Hierarchical views (.secondary, .tertiary, .quaternary)
  • Gradients

Using Background

Because the background of the VStack touches the edge of the safe area, the purple color will bleed into the safe area.

var body: some View {
    VStack {
        Text("Hello, World!")
        Divider()
        Spacer()
    }
    .background(Color.purple)
}

TabView

In iOS 15 the TabView is no longer translucent. Meaning the background color will bleed right into it.

Background color in TabView

If you want to provide a custom style for your TabView, you can add another Style that touches the bottom safe area edge so that bleeds into your TabView. For example:

var body: some View {
    TabView {
        VStack {
            Text("Hello, World!")
            Divider()
            Spacer()
            // Bleeds into TabView
            Rectangle()
                .frame(height: 0)
                .background(.thinMaterial)
        }
        .background(Color.purple)
        .tabItem {
            Text("Tab 1")
            Image(systemName: "wifi")
        }
    }
}

TabView with Style

NavigationView

The same thing that happens to TabView will also happen with NavigationView.

To customize the NavigationView style, add a style that will touch the top safe area edge and it will bleed into the NavigationView:

var body: some View {
    NavigationView {
        VStack {
            // Bleeds into NavigationView
            Rectangle()
                .frame(height: 0)
                .background(.ultraThinMaterial)
            Text("Hello, World!")
            Divider()
            Spacer()
        }
        .background(Color.purple)
        .navigationTitle(Text("Style"))
    }
}

NavigationView with Style

I'm totally open to other ways of accomplishing this. Leave a comment or edit this answer if you know of other ways.

Mark Moeykens
  • 15,915
  • 6
  • 63
  • 62
  • 7
    Do you know how to change background color for NavigationView? – atalayasa Jun 20 '19 at 11:40
  • 3
    This will work however if you have a NavigationView and a list or scrollview the navigation bar title will not collapse – Richard Witherspoon Sep 05 '19 at 17:08
  • Thanks, @RichardWitherspoon, do you mean the ZStack or Overlay solution? Or both? – Mark Moeykens Sep 05 '19 at 17:10
  • 2
    I just tried both with no luck. Ive been trying to figure out a way to get the screen background color working with a navigationView and scrollview – Richard Witherspoon Sep 05 '19 at 17:11
  • Using .edgesIgnoringSafeArea(.all) work for me, but I don't like this solution because in my app, I don't want to use .edgesIgnoringSafeArea(.all) for other interface elements. Hopefully SwiftUI will have a better solution soon since I can imagine that changing your background color would be a popular request. – Ryan Sep 28 '19 at 05:35
  • 1
    Hey @Ryan, I updated my solutions to move `.edgesIgnoringSafeArea(.all)` to just the color and not any of the other content. This should work better for you. – Mark Moeykens Sep 30 '19 at 19:50
  • 2
    Regarding NavigationView, use the ZStack method above just inside the NavigationView as shown here: https://stackoverflow.com/a/58230473/457478 – Ryan Oct 15 '19 at 17:15
  • 1
    On iPhone >X, how do you get the color to apply to the top-most portion of the screen where the time, signal strength, wifi, battery, etc. are located? – Adrian Dec 06 '20 at 16:54
194

You can do something like:

.background(Color.black)

around your view.

eg. from the default template (I am encompassing it around a Group):

    var body: some View {
        VStack {
          Text("Hello SwiftUI!")
        }
       .background(Color.black)
    }

To add some opacity to it, you can add the .opacity method as well:

.background(Color.black.opacity(0.5))

You can also make use of the inspect element of the view by CMD + click on the View and clicking Show SwiftUI Inspector > Background > Your Color

Inspect View

Inspect Detail View

Simon
  • 6,413
  • 6
  • 34
  • 57
56

Background Color

(Xcode 14.3, iOS 16.4, SwiftUI 4.0)

enter image description here

1. Text

To dilate a BG color on Text view, use maxWidth and maxHeight parameters of .frame() modifier.

var body: some View {             // PINK COLOR
    Text("one")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .foregroundColor(.white)
        .font(.system(size: 100))
        .background(.pink)
}

2. ZStack

To fill a ZStack view's background, use Color object as the base layer.

var body: some View {             // YELLOW COLOR
    ZStack {
        Color.yellow.ignoresSafeArea()
        Text("two").font(.system(size: 100))
    }
}

3. VStack | HStack

In case you want to assign a new BG color to VStack or HStack, apply modifiers to the stack itself.

var body: some View {             // TEAL COLOR
    VStack {
        Text("three").font(.system(size: 100))
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(.teal)
}

enter image description here

4. Gradient

You're capable of using Rectangle that ignores screen's safe area and fills a screen with a gradient.

var body: some View {             // PURPLISH GRADIENT
    ZStack {
        Rectangle()
            .fill(Gradient(colors: [.indigo, .purple]))
            .ignoresSafeArea()
        Text("four").font(.system(size: 100))
            .foregroundColor(.white)
    }
}

5. Color Scheme | Color Invert

Color inversion is a simple and smart solution.

var body: some View {             // INVERSION OF A COLOR
    ZStack {
        List {
            ForEach(1..<6) { version in
                HStack {
                    Image(systemName: "swift")
                    Text("Swift \(version).0")
                }
            }
        }
        Text("five").font(.system(size: 100))
    }
    .environment(\.colorScheme, .dark)
    // .colorInvert()
}

6. Image

An unindented image can contain a solid color or a gradient.

var body: some View {             // GREEN JPEG as BG COLOR
    ZStack {
        Image("green")
            .resizable()
            .ignoresSafeArea()
            .brightness(-0.2)
        Text("six").font(.system(size: 100))
            .foregroundColor(.white)
    }
}

Blend Modes

In SwiftUI, there is also the compositing technique that affects background color and/or image color. Read about "photoshopic" blend modes HERE.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
39

Fill the entire screen:

var body: some View {
    Color.green.edgesIgnoringSafeArea(.all)
}
Code Result
Image of code Screen is completely green, even area around notch
aheze
  • 24,434
  • 8
  • 68
  • 125
Malik
  • 921
  • 11
  • 12
26

like this

struct ContentView : View {
    @State var fullName: String = "yushuyi"
    var body: some View {        
        VStack
            {
                TextField($fullName).background(SwiftUI.Color.red)
                Spacer()
        }.background(SwiftUI.Color.yellow.edgesIgnoringSafeArea(.all))
    }
}
余书懿
  • 261
  • 2
  • 3
18

For List:

All SwiftUI's Lists are backed by a UITableViewin iOS. so you need to change the background color of the tableView. But since Color and UIColor values are slightly different, you can get rid of the UIColor.

struct ContentView : View {
    init(){
        UITableView.appearance().backgroundColor = .clear
    }
    
    var body: some View {
        List {
            Section(header: Text("First Section")) {
                Text("First Cell")
            }
            Section(header: Text("Second Section")) {
                Text("First Cell")
            }
        }
        .background(Color.yellow)
    }
}

Now you can use Any background (including all Colors) you want


Also First look at this result:

View hierarchy

As you can see, you can set the color of each element in the View hierarchy like this:

struct ContentView: View {
    
    init(){
        UINavigationBar.appearance().backgroundColor = .green 
        //For other NavigationBar changes, look here:(https://stackoverflow.com/a/57509555/5623035)
    }

    var body: some View {
        ZStack {
            Color.yellow
            NavigationView {
                ZStack {
                    Color.blue
                    Text("Some text")
                }
            }.background(Color.red)
        }
    }
}

And the first one is window:

window.backgroundColor = .magenta

The very common issue is we can not remove the background color of SwiftUI's HostingViewController (yet), so we can't see some of the views like navigationView through the views hierarchy. You should wait for the API or try to fake those views (not recommended).

Community
  • 1
  • 1
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • a similar question, instead of setting a color on List row, how can I make it transparent, it seems all my attempts fail to reveal the underlying color and rows stay white, particularly, there's `ListCoreCellHost` that stays white. https://pasteboard.co/JeWCgMV.png – atastrophic Jun 26 '20 at 23:53
  • Okay I figured 15 minutes later posting here, had to set `UITableViewCell.appearance().backgroundColor = .clear` as well. :) – atastrophic Jun 27 '20 at 00:09
9
struct Soview: View {
    var body: some View {
        VStack{
            Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
                .frame(maxWidth:.infinity,maxHeight: .infinity)
        }.background(Color.yellow).ignoresSafeArea(.all)
    }
}
guoliang li
  • 91
  • 1
  • 3
9

iOS Deployment Target 15 → Use the modifier .background(Color).


If your app needs to be compatible with older SwiftUI versions, e.g. that of iOS 14, you can follow Apple's advice and make a temporary ViewModifier:

Adopt the ViewModifier protocol when you want to create a reusable modifier that you can apply to any view.

You can apply modifier(_:) directly to a view, but a more common and idiomatic approach uses modifier(_:) to define an extension to View itself that incorporates the view modifier

Source:  Developer Documentation > SwiftUI > View Fundamentals > ViewModifier

extension View {
  @available(iOS, deprecated: 15.0, message: "No longer needed, use the default background modifier instead")
  func backgroundColor(_ color: Color) -> some View {
    modifier(BackgroundColorModifier(color: color))
  }
}

struct BackgroundColorModifier: ViewModifier {
  var color: Color

  func body(content: Content) -> some View {
    if #available(iOS 15.0, *) {
      content
        .background(color)
    } else {
      ZStack {
        color // background
        content
      }
    }
  }
}

Then you can apply .backgroundColor(_:) on any View:

var body: some View {
  ScrollView() {
    …
  }
  .backgroundColor(.red)
}

When your app no longer supports the older iOS version, you will be warned that your custom view modifier is no longer required … clean-up time!

PDK
  • 1,476
  • 1
  • 14
  • 25
  • Simple easy and maintainable perfect thanks! – YanSte Aug 10 '22 at 10:31
  • I like this, but I'm having an issue... the View's width and height gets messed when I use it on iOS14. I needed to add `.fixedSize(horizontal: true, vertical: true)` to every view that use this. It's kind of ugly. Do you have a better solution or am I missing something? – sebasira Dec 16 '22 at 13:23
  • Update on this. I could also solve it by specifiying min, ideal and max altogether for W and H – sebasira Dec 16 '22 at 18:22
6

Several possibilities : (SwiftUI / Xcode 11)

1 .background(Color.black) //for system colors

2 .background(Color("green")) //for colors you created in Assets.xcassets

  1. Otherwise you can do Command+Click on the element and change it from there.

Hope it help :)

6

You can Simply Change Background Color of a View:

var body : some View{


    VStack{

        Color.blue.edgesIgnoringSafeArea(.all)

    }


}

and You can also use ZStack :

var body : some View{


    ZStack{

        Color.blue.edgesIgnoringSafeArea(.all)

    }


}
MannaICT13
  • 189
  • 2
  • 9
6

I like to declare a modifier for changing the background color of a view.

extension View {
  func background(with color: Color) -> some View {
    background(GeometryReader { geometry in
      Rectangle().path(in: geometry.frame(in: .local)).foregroundColor(color)
    })
  }
}

Then I use the modifier by passing in a color to a view.

struct Content: View {

  var body: some View {
    Text("Foreground Label").foregroundColor(.green).background(with: .black)
  }

}

enter image description here

jnblanchard
  • 1,182
  • 12
  • 12
3

Would this solution work?:

add following line to SceneDelegate: window.rootViewController?.view.backgroundColor = .black

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        if let windowScene = scene as? UIWindowScene {

                window.rootViewController?.view.backgroundColor = .black
}
saxjax
  • 89
  • 6
3

Xcode 11.5

Simply use ZStack to add background color or images to your main view in SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.black
        }
        .edgesIgnoringSafeArea(.vertical)
    }
}
Prashant Gaikwad
  • 3,493
  • 1
  • 24
  • 26
3

I don't know why nobody said this, but the background() modifier is intended to set background color and does support ignoresSafeArea():

var body: some View {
    Text("Da ba dee")
        .background(Color.blue.ignoresSafeArea())
}
kelin
  • 11,323
  • 6
  • 67
  • 104
2

Use Below Code for Navigation Bar Color Customization

struct ContentView: View {

@State var msg = "Hello SwiftUI"
init() {
    UINavigationBar.appearance().backgroundColor = .systemPink

     UINavigationBar.appearance().largeTitleTextAttributes = [
        .foregroundColor: UIColor.white,
               .font : UIFont(name:"Helvetica Neue", size: 40)!]

    // 3.
    UINavigationBar.appearance().titleTextAttributes = [
        .font : UIFont(name: "HelveticaNeue-Thin", size: 20)!]

}
var body: some View {
    NavigationView {
    Text(msg)
        .navigationBarTitle(Text("NAVIGATION BAR"))       
    }
    }
}

enter image description here

ShigaSuresh
  • 1,598
  • 17
  • 19
0

NavigationView Example:

var body: some View {
    var body: some View {
        NavigationView {
            ZStack {
                // Background
                Color.blue.edgesIgnoringSafeArea(.all)

                content
            }
            //.navigationTitle(Constants.navigationTitle)
            //.navigationBarItems(leading: cancelButton, trailing: doneButton)
            //.navigationViewStyle(StackNavigationViewStyle())
        }
    }
}

var content: some View {
    // your content here; List, VStack etc - whatever you want
    VStack {
       Text("Hello World")
    }
}
Rajee Jones
  • 289
  • 2
  • 9
0

To make a central/reusable background widget, you can do something like this -

import SwiftUI
struct BgView<Content>: View where Content: View {
        private let content: Content
    
        public init(@ViewBuilder content: () -> Content) {
            self.content = content()
        }
    
        var body : some View {
            ZStack {
              Color.black.ignoresSafeArea()
                content
            }
          } 
    }

And can easily use in all of your views like below -

import SwiftUI

struct TestView: View {
    var body: some View {
      BgView{
        Text("Hello, World!")
      }.foregroundColor(.white)
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}
Pramod
  • 1,123
  • 2
  • 12
  • 33
0

Solution:

You can make a coloured view and set it as VStack background.

struct ColoredView: UIViewRepresentable {
    var color: Color
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.backgroundColor = UIColor(color)
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = .clear
        }
        return view
    }
    func updateUIView(_ uiView: UIView, context: Context) {}
}

Usage:

 VStack {
    Text("VStack with Red backgound")
    Text("VStack with Red backgound")
    Text("VStack with Red backgound")
    Text("VStack with Red backgound")
 }.background(ColoredView(color: .red))

Result: enter image description here

Ali Murad
  • 122
  • 1
  • 5
0

Firstly you should use the

 ZStack {
      Color("Desired_color_name").ignoresSafeArea()
// if you create any color set then give that colour set name
// otherwise use Color.gray or as you want the colour name
    
     //Here you should start your design
    }
-13

The code on Scene delegate in Swift UI

Content view background-color

window.rootViewController?.view.backgroundColor = .lightGray

Srinivasan_iOS
  • 972
  • 10
  • 12