Skip to content
All articles

SwiftUI Scroll Edge Effect: Soft vs Hard, and the iOS 27 Change

How the SwiftUI scroll edge effect works on iPhone and iPhone Duo: .soft vs .hard, why bars look solid on iOS 27, restoring the iOS 26 fade, and the UIKit API.

By AppleDuo EditorialPublished 7 min read

Also available in:DeutschEspañolFrançais日本語Türkçe

On this page
  1. What is the scroll edge effect in SwiftUI?
  2. What's the difference between .soft and .hard?
  3. Why does the scroll edge effect look different on iOS 27?
  4. How do I get the iOS 26 scroll edge fade back on iOS 27?
  5. How do I set or hide the scroll edge effect for one edge?
  6. How do I change the scroll edge effect in UIKit?
  7. How does the scroll edge effect work with iPhone Duo's vertical bar?
  8. Key takeaways

Rebuild an app with Xcode 27 and its navigation bars may suddenly look different. Where content used to fade softly under the toolbar, there's now a firm line and a more solid band. Nothing in your code changed. What changed is the default scroll edge effect in SwiftUI, the treatment iOS applies where scrolling content meets a bar.

This guide explains what the scroll edge effect is, how .soft and .hard differ, what changed between iOS 26 and iOS 27, and how to pick the look you want in SwiftUI and UIKit. It's based on Apple's documentation and WWDC25 sessions, an Apple engineer's answer on the developer forums, and reports from developers including @sarunw. The iOS 27 change isn't in Apple's release notes, so treat it as observed behavior that can change between releases.

What is the scroll edge effect in SwiftUI?

The scroll edge effect arrived in iOS 26 as part of Liquid Glass. Toolbars no longer sit on an opaque background; their items float over your content. To keep those items legible, the system treats the content that scrolls under them. Apple's WWDC25 session Build a SwiftUI app with the new design calls it "a subtle blur and fade effect applied to content under system toolbars."

You get it automatically under system bars. Apple asks you to remove any extra backgrounds or darkening layers you placed behind bar items, because they interfere with the effect. Custom bars can join in too: SwiftUI's safeAreaBar(edge:alignment:spacing:content:), new in iOS 26, shows content as a custom bar beside a view, and scroll views under it get an edge effect like the one under a system bar.

You control the effect with scrollEdgeEffectStyle(_:for:), also new in iOS 26. It applies to scroll views anywhere inside the view you modify, so you can set it on a container rather than on each scroll view.

What's the difference between .soft and .hard?

ScrollEdgeEffectStyle has three values. Apple defines them like this:

StyleApple's definitionTypical use
.automaticApplied by the system when pinned content overlaps scrolling contentThe default; lets iOS decide
.softA subtle, blurred boundary between pinned controls and scrolling contentThe fade most apps had at the top on iOS 26
.hardA linear, nearly opaque boundary between pinned controls and scrolling contentDense interfaces with many floating elements

Apple's own example of a dense interface is the Calendar app. In the UIKit version of the session, Apple says the hard style looks similar to the standard bar backgrounds in iOS 18. Here is the sample from the SwiftUI session:

ScrollView {
    // content
}
.scrollEdgeEffectStyle(.hard, for: .top)

Why does the scroll edge effect look different on iOS 27?

Two things changed, and they're easy to mix up.

The default changed. @sarunw sums it up: "In iOS 26, the scroll edge effect default is .soft. In iOS 27, it is .hard." Developers saw the same thing in their own apps. The Shellbee project filed a bug when bars across its app went flat after an iOS 27 build, and DevelopersIO found the same for a custom safeAreaBar. Strictly, the default is still .automatic; what it resolves to is what changed. DevelopersIO also reports that an app built with Xcode 26.6 and run on iOS 27 kept the old look, so the change follows the SDK you build with. Its author found no mention in the iOS 27 or Xcode 27 release notes.

The styles themselves changed. @sarunw notes that .hard isn't the same on both versions. On iOS 26 it's almost a solid bar, and text behind it is unreadable. On iOS 27, the cutoff line stays, but content still shows through. In Dark Mode, he describes the same split: .soft fades, .hard cuts, and the iOS 27 style is more balanced. Apple changed .soft too. On the developer forums, an Apple engineer wrote that "the .soft style has changed substantially in iOS 27."

iOS 26iOS 27
.automatic at the top, per developer reportsResolves to softResolves to hard
.hard look, per @sarunwAlmost solid; text behind is unreadableA cutoff line; content shows through
.soft lookBlur and fadeRedesigned, per Apple's engineer

Why the switch? Apple hasn't said publicly. The same forum answer notes that many apps chose .soft explicitly where .automatic would have been more appropriate, and that .soft "is not the OS default."

How do I get the iOS 26 scroll edge fade back on iOS 27?

If your design depends on the fade, ask for it. @sarunw's fix is one modifier:

List(items) { item in
    ItemRow(item: item)
}
.scrollEdgeEffectStyle(.soft, for: .top)

If you still support releases before iOS 26, wrap it in an availability check so you can apply it everywhere with one call:

extension View {
    @ViewBuilder
    func softTopScrollEdge() -> some View {
        if #available(iOS 26.0, *) {
            scrollEdgeEffectStyle(.soft, for: .top)
        } else {
            self
        }
    }
}

Three caveats. First, Shellbee's fix notes that a style set at the app root didn't reach NavigationStacks presented as sheets or full-screen covers, so apply it inside each one. Second, "back" isn't exact: since .soft was redesigned in iOS 27, you get iOS 27's soft look, not a pixel match for iOS 26. Third, Apple's engineer recommends .automatic wherever it meets your design needs, and points out that .soft may not suit every design.

There was also a compatibility bug. A developer forums thread reported that .soft rendered fully transparent above a safeAreaBar on iOS 27 betas, but only in apps built with the iOS 26 SDK. Apple said iOS 27.2 would make the new .soft available to those apps, and a later post in the thread reports it fixed in iOS 27.2 beta 4. If you ship an iOS 26-linked build, check it on iOS 27.2.

How do I set or hide the scroll edge effect for one edge?

The second parameter of scrollEdgeEffectStyle(_:for:) is an Edge.Set, so you choose which edges a style applies to: one edge, several, or .all. DevelopersIO's fix for its custom bottom bar targets only that edge:

ScrollView {
    DayList()
}
.scrollEdgeEffectStyle(.soft, for: .bottom)
.safeAreaBar(edge: .bottom) {
    DayPicker()
}

Its author notes that the modifier can sit on an outer view that wraps the scroll view, as here.

To remove the effect, use scrollEdgeEffectHidden(_:for:), new in iOS 26. Both parameters have defaults, so the bare modifier hides every edge:

ScrollView {
    PhotoGrid()
}
.scrollEdgeEffectHidden(true, for: .bottom)

Hide it only when nothing pinned sits over that edge, or when your own design already keeps the controls legible. Otherwise, glass buttons end up over unprocessed content.

How do I change the scroll edge effect in UIKit?

UIKit has the same model, also new in iOS 26. Each UIScrollView exposes topEdgeEffect, bottomEdgeEffect, leftEdgeEffect and rightEdgeEffect. Each one is a UIScrollEdgeEffect with a style of .automatic, .soft or .hard, and an isHidden flag that defaults to false.

tableView.topEdgeEffect.style = .soft
collectionView.bottomEdgeEffect.isHidden = true

For your own views over a scroll view's edge, such as a row of buttons, Apple's Build a UIKit app with the new design session uses UIScrollEdgeElementContainerInteraction. Descendants of the container, like labels, images and controls, then shape the edge effect.

let interaction = UIScrollEdgeElementContainerInteraction()
interaction.scrollView = scrollView
interaction.edge = .bottom
buttonContainer.addInteraction(interaction)

Most reports of the iOS 27 default change come from SwiftUI projects, and the forum thread above includes a UIKit developer seeing the .soft bug. Check UIKit screens on iOS 27 too rather than assuming they're unaffected.

How does the scroll edge effect work with iPhone Duo's vertical bar?

On iPhone Duo, apps built with the iOS 27.1 SDK move navigation and toolbar items into a vertical bar along one side edge. Apple's Raise the bar with iPhone Duo Tech Talk says a vertical bar "doesn't have a scroll-edge effect by default," the same as horizontal bars, and that it does get a background when Reduce Transparency is on. Apple asks you to keep custom views in the bar legible either way. Our guide to the iPhone Duo vertical toolbar covers when bars go vertical.

Apple doesn't document how scrollEdgeEffectStyle with .leading or .trailing interacts with the vertical bar, so don't build on assumptions there. Inner-display portrait keeps horizontal bars, so a style you set for .top matters on the same device that shows a vertical bar in landscape. Check both orientations, and keep content clear of the bar with the right safe areas and content margins.

Key takeaways

  • The scroll edge effect, new in iOS 26, keeps Liquid Glass bars legible over scrolling content. Set it with scrollEdgeEffectStyle(_:for:) and hide it with scrollEdgeEffectHidden(_:for:).
  • .soft is a blurred boundary and .hard a nearly opaque one; Apple suggests .hard for dense interfaces.
  • Developers report that iOS 27 builds resolve the automatic top effect to .hard, and both styles look different on iOS 27.
  • To keep a fade, apply .scrollEdgeEffectStyle(.soft, for: .top), including inside modal NavigationStacks.
  • In UIKit, use topEdgeEffect.style and isHidden on each UIScrollView edge.
  • On iPhone Duo, vertical bars have no scroll edge effect by default, so check both orientations.

For more on how iOS 26 toolbars group and style their items, read our SwiftUI toolbar guide for Liquid Glass. To see apps and games that already make the most of the device, browse Built for the fold.

Frequently asked questions

What is the scroll edge effect in SwiftUI?

It's the treatment iOS 26 applies to content that scrolls under toolbars and other pinned controls, so the controls stay legible. SwiftUI applies it automatically, and you change it with scrollEdgeEffectStyle(_:for:) or remove it with scrollEdgeEffectHidden(_:for:).

What is the difference between .soft and .hard?

Apple describes .soft as a subtle, blurred boundary between pinned controls and scrolling content, and .hard as a linear, nearly opaque boundary. Apple suggests .hard for dense interfaces with many floating elements.

Why does my toolbar look solid on iOS 27?

Developers report that when an app is built with the iOS 27 SDK, the automatic top scroll edge effect resolves to .hard instead of the iOS 26 .soft fade. Apple's release notes don't mention it, so set the style explicitly if you depend on one look.

How do I bring back the iOS 26 scroll edge fade on iOS 27?

Apply .scrollEdgeEffectStyle(.soft, for: .top) to the scroll view or a container around it. Apply it inside every NavigationStack you present as a sheet or full-screen cover too, since developers report that modal stacks don't inherit it from the root.

How do I change the scroll edge effect in UIKit?

Each UIScrollView has topEdgeEffect, bottomEdgeEffect, leftEdgeEffect and rightEdgeEffect properties. Set an edge's style to .soft, .hard or .automatic, or set isHidden to true to remove it.

Sources

  1. scrollEdgeEffectStyle(_:for:) · Apple Developer Documentation
  2. ScrollEdgeEffectStyle · Apple Developer Documentation
  3. scrollEdgeEffectHidden(_:for:) · Apple Developer Documentation
  4. safeAreaBar(edge:alignment:spacing:content:) · Apple Developer Documentation
  5. UIScrollEdgeEffect · Apple Developer Documentation
  6. UIScrollEdgeElementContainerInteraction · Apple Developer Documentation
  7. Build a SwiftUI app with the new design · Apple Developer (WWDC25)
  8. Build a UIKit app with the new design · Apple Developer (WWDC25)
  9. Raise the bar with iPhone Duo · Apple Developer
  10. iOS 27 beta 1: .scrollEdgeEffectStyle(.soft) renders fully transparent above safeAreaBar · Apple Developer Forums
  11. Xcode 27: safeAreaBar's effect changed to the equivalent of hard · DevelopersIO (Classmethod)
  12. iOS 27 changes scroll-edge toolbar default from soft to hard · Shellbee on GitHub
  13. In iOS 26, the scroll edge effect default is .soft. In iOS 27, it is .hard · @sarunw on X
  14. .hard is not the same on iOS 26 and iOS 27 · @sarunw on X
  15. Same scroll edge styles in Dark Mode · @sarunw on X
  16. Want the iOS 26 scroll edge fade back on iOS 27? · @sarunw on X

Make the fold part of your app.

We showcase apps and games that do something real with iPhone Duo. Send us yours with a link to it on the App Store, or see what other developers have built.

[email protected]