RSS Feed ↗
VOL. 1 • NO. 14 • IOSBUFFET.COM OCT 25, 2026
Inside Page — A8 Continued from Front
The Daily Recipe
Sep 29, 2026 • Page A8

Edge-to-Edge Hero Header

A detail screen whose photo runs under the navigation bar and the iPad sidebar, with a soft blur where content meets the toolbar and glass buttons grouped the way iOS 26 intends.

By M. HOSSAIN — Staff Writer — Sep 29, 2026 1490 words
Recipe Card — No. 7
Serves
iOS 26+ · iPhone and iPad
Prep time
20 minutes
Kitchen-tested
Compiled with Xcode 26.6 · iOS 26.5 simulator · Oct 26, 2026
Difficulty
★☆☆
Ingredients
  • .backgroundExtensionEffect()
  • .scrollEdgeEffectStyle(_:for:)
  • ToolbarSpacer(.fixed, placement:)
  • .navigationSubtitle(_:)
  • .ignoresSafeArea(edges: .top)
  • A NavigationSplitView to show it off on iPad

The detail screens in Apple’s own iOS 26 apps share a look: the hero photo doesn’t stop at the navigation bar, it runs right up under it, and on iPad it keeps going underneath the translucent sidebar. Where the list scrolls beneath the toolbar there is no hard line, just a soft fade. None of this needs custom blur views anymore. It comes from a handful of new modifiers.

This recipe builds a recipe-detail screen (a cookbook within a cookbook) with that treatment, inside a split view so it works on both iPhone and iPad.

Method

1. Start with a split view

On iPad the sidebar floats over the detail column as a glass panel. That is exactly where the background extension effect earns its keep. On iPhone the same code collapses into a normal navigation stack.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct Recipe: Identifiable, Hashable {
    let id = UUID()
    let title: String
    let summary: String
    let heroImage: String
    let minutes: Int
    let servings: Int
    let steps: [String]
}

struct CookbookView: View {
    let recipes: [Recipe]
    @State private var selection: Recipe?

    var body: some View {
        NavigationSplitView {
            List(recipes, selection: $selection) { recipe in
                NavigationLink(recipe.title, value: recipe)
            }
            .navigationTitle("Cookbook")
        } detail: {
            if let selection {
                RecipeDetailView(recipe: selection)
            } else {
                ContentUnavailableView("Pick a Recipe", systemImage: "fork.knife")
            }
        }
    }
}

2. Pull the hero under the bars

Two modifiers do different jobs here, and the difference matters. .ignoresSafeArea(edges: .top) lets the scroll view’s content start at the very top of the screen, so the photo sits under the navigation bar. .backgroundExtensionEffect() then fills any remaining safe-area edges around the image — under the iPad sidebar, or the side insets of an iPhone in landscape — with mirrored, blurred copies of it, so the image appears to continue beneath the glass.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct RecipeDetailView: View {
    let recipe: Recipe

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 0) {
                Color.clear
                    .frame(height: 360)
                    .overlay {
                        Image(recipe.heroImage)
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                    }
                    .clipped()
                    .backgroundExtensionEffect()

                VStack(alignment: .leading, spacing: 12) {
                    Text(recipe.title)
                        .font(.largeTitle.bold())
                    Text(recipe.summary)
                        .foregroundStyle(.secondary)
                    ForEach(Array(recipe.steps.enumerated()), id: \.offset) { index, step in
                        Label(step, systemImage: "\(index + 1).circle")
                    }
                }
                .padding()
            }
        }
        .ignoresSafeArea(edges: .top)
        .scrollEdgeEffectStyle(.soft, for: .top)
        .navigationTitle(recipe.title)
        .navigationSubtitle("\(recipe.minutes) min · Serves \(recipe.servings)")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar { RecipeToolbar() }
    }
}

Why the Color.clear and overlay? An image with .aspectRatio(contentMode: .fill) and only a height still reports its natural width: a landscape photo 360 points tall is wider than an iPhone screen. Put it straight in the stack and it widens the whole column, pushing the title and text off the leading edge; .clipped() hides the overflow but doesn’t fix the layout. Color.clear takes exactly the width it’s offered, so the photo fills that box and nothing more. (Our first draft of this recipe had exactly that bug, and the test kitchen’s screenshots caught it.)

Apply the extension effect to a single background view, not to every image on the screen. Apple’s documentation is explicit about using it with discretion: each use duplicates the view and blurs the copies, and the modifier clips the view so the copies never overlap it.

3. Soften the edge

Scroll views already draw an automatic edge effect where content passes under a toolbar. .scrollEdgeEffectStyle(.soft, for: .top) asks for the subtle, blurred version; .hard gives a crisper, nearly opaque boundary, which suits dense text such as a spreadsheet or a code editor. Pass .automatic to go back to the system choice.

4. Group the toolbar the iOS 26 way

In iOS 26, toolbar items sit on glass, and adjacent items share one glass capsule. Use ToolbarSpacer to split them into groups by meaning: the everyday actions together, the primary action on its own.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct RecipeToolbar: ToolbarContent {
    var body: some ToolbarContent {
        ToolbarItemGroup(placement: .topBarTrailing) {
            Button("Favourite", systemImage: "heart") { }
            Button("Share", systemImage: "square.and.arrow.up") { }
        }

        ToolbarSpacer(.fixed, placement: .topBarTrailing)

        ToolbarItem(placement: .topBarTrailing) {
            Button("Start Cooking", systemImage: "flame") { }
        }
    }
}

.fixed inserts a standard gap. .flexible expands to fill whatever space is left, which is useful in a bottom toolbar to push items to opposite ends.

Plating

On iPhone the photo fills the top of the screen with the back button and the two toolbar capsules floating over it. Scroll up and the text slides under the toolbar through a soft blur, while the inline title and its “35 min · Serves 4” subtitle take over. On iPad, open the sidebar: instead of the photo stopping at the sidebar’s edge, a blurred reflection of it continues underneath the glass, and the detail column feels full-bleed.

Detail
Detail
Scrolled
Scrolled
FIG. 1 — On iPhone the photo runs under the navigation bar; scrolled, the text passes under the toolbar through the soft edge effect.
iPad, landscape
iPad, landscape
FIG. 2 — On iPad the background extension effect continues the photo beneath the sidebar.

Kitchen notes

  • Subtitle availability. navigationSubtitle has existed on macOS since 2022 but only arrived on iOS and iPadOS in 26. If you still support iOS 18, guard it with if #available(iOS 26, *) inside a small view modifier.
  • Legibility over photos. Toolbar glass adapts to what’s behind it, but a very bright or very busy photo can still fight the title. A subtle dark gradient at the top of the image helps more than you’d think.
  • Hiding a single item’s glass. For an item that should not get the shared glass background, such as a profile avatar, apply .sharedBackgroundVisibility(.hidden) to that ToolbarItem.
  • One hero per screen. Stacking several background extensions on one screen costs performance and muddies the effect. Pick the one image that defines the screen.

— 30 —

— END OF EDITION 2026 — SET IN GARAMOND & COURIER ON NEWSPRINT STOCK — iOS BUFFET PRESS — RSS —