---
title: Always Respect Safe Areas
impact: MEDIUM-HIGH
impactDescription: prevents 100% of content clipping behind Dynamic Island, notch, and home indicator — eliminates the #1 cause of "can't tap button" support tickets
tags: thorough, safe-area, layout, rams-8, rams-2, dynamic-island
---

## Always Respect Safe Areas

The button behind the home indicator that you can see but cannot tap — like a door handle placed behind a wall. You know it is there, you can read the label, but your finger lands on the system gesture zone instead of the button every single time. Calling `.ignoresSafeArea()` without understanding what it disables is how this happens: the background correctly bleeds to the screen edges, but the interactive content goes with it, sliding behind hardware that the user cannot override. Backgrounds extend to edges; content stays within safe areas. That distinction is the difference between a polished full-bleed layout and a broken one.

**Incorrect (ignoresSafeArea hides text and buttons behind hardware):**

```swift
struct LiveActivityView: View {
    var body: some View {
        ZStack {
            Color.black

            VStack(spacing: 16) {
                // This text renders behind the Dynamic Island on iPhone 15+
                Text("LIVE")
                    .font(.caption.bold())
                    .foregroundStyle(.red)

                Text("Golden State Warriors vs. Boston Celtics")
                    .font(.title3.bold())
                    .foregroundStyle(.white)

                Text("Q3 · 4:28")
                    .font(.headline)
                    .foregroundStyle(.white.opacity(0.8))

                Spacer()

                // This button sits behind the home indicator
                Button("Open Full Scoreboard") { }
                    .buttonStyle(.borderedProminent)
                    .padding(.bottom, 8)
            }
            .padding()
        }
        // Blanket ignore — content now collides with hardware on every edge
        .ignoresSafeArea()
    }
}
```

**Correct (background extends to edges, content stays within safe areas):**

```swift
struct LiveActivityView: View {
    var body: some View {
        VStack(spacing: 16) {
            Text("LIVE")
                .font(.caption.bold())
                .foregroundStyle(.red)

            Text("Golden State Warriors vs. Boston Celtics")
                .font(.title3.bold())
                .foregroundStyle(.white)

            Text("Q3 · 4:28")
                .font(.headline)
                .foregroundStyle(.white.opacity(0.8))

            Spacer()

            Button("Open Full Scoreboard") { }
                .buttonStyle(.borderedProminent)
        }
        .padding()
        // Background extends to edges — content does not
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.ignoresSafeArea())
    }
}
```

**Custom bottom bar using safeAreaInset:**

```swift
struct ChatView: View {
    @State private var message = ""

    var body: some View {
        ScrollView {
            LazyVStack {
                // Chat messages...
                ForEach(0..<20) { i in
                    Text("Message \(i)")
                        .padding()
                        .frame(maxWidth: .infinity, alignment: .leading)
                }
            }
        }
        // safeAreaInset pushes scroll content UP so it is never hidden
        .safeAreaInset(edge: .bottom) {
            HStack {
                TextField("Message", text: $message)
                    .textFieldStyle(.roundedBorder)
                Button(action: { /* send */ }) {
                    Image(systemName: "arrow.up.circle.fill")
                        .font(.title2)
                }
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 8)
            .background(.bar)
        }
    }
}
```

**Safe area rules by content type:**

```swift
// Content type         | Ignore safe area? | Method
// ----------------------|-------------------|----------------------------------
// Background color      | Yes               | .background(Color.x.ignoresSafeArea())
// Background image      | Yes               | .ignoresSafeArea() on the image only
// Text content          | Never             | Default behavior (respects safe area)
// Buttons / controls    | Never             | Default behavior
// Custom top/bottom bar | No — use inset    | .safeAreaInset(edge:)
// Scroll content        | No                | .contentMargins() on iOS 17+
// Full-screen media     | Yes (video only)  | .ignoresSafeArea() with controls overlay
```

**When NOT to apply:** Full-screen video playback, camera viewfinders, and immersive AR experiences legitimately ignore all safe areas. In those cases, overlay interactive controls (play/pause, close) within the safe area using a separate layer.

Reference: [Layout - Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/layout)
