Blur Fade Transition
A custom transition that combines blur, fade and scale, available as .blurFade.

- Transitions
- iOS 18.0+
- beginner
- Origin
- Original work
- Found by
- transition · blur · fade · scale · appear · disappear · custom transition · transición · desenfoque · fundido · escala · aparecer · desaparecer
Description
Section titled “Description”A transition that blurs, fades and scales a view. Use it as .transition(.blurFade).
With Reduce Motion on, the view only fades.
struct BlurFadeTransitionDemo: View { @State private var isShown = true
var body: some View { ZStack { LinearGradient(colors: [.black, .indigo], startPoint: .top, endPoint: .bottom) .ignoresSafeArea()
if isShown { VStack(spacing: 14) { Image(systemName: "moon.stars.fill") .font(.largeTitle) .imageScale(.large) .symbolRenderingMode(.hierarchical) .accessibilityHidden(true)
Text("Good night") .font(.system(.largeTitle, design: .rounded, weight: .bold))
Text("Sleep mode starts in ten minutes.") .font(.callout) .opacity(0.8) } .foregroundStyle(.white) .multilineTextAlignment(.center) .padding(36) .frame(maxWidth: .infinity) .background(.white.opacity(0.12), in: .rect(cornerRadius: 32)) .padding(28) .transition(.blurFade) } } .task { while (try? await Task.sleep(for: .seconds(1.3))) != nil { withAnimation(.smooth(duration: 0.6)) { isShown.toggle() } } } }}API reference
Section titled “API reference”| Parameter | Type | Default |
|---|---|---|
radius | CGFloat | 18 |
scale | CGFloat | 0.9 |
Copy this code into your project, or download the file.
// SPDX-License-Identifier: MIT// Copyright (c) 2026 Oscar Canton and SwiftUI Blocks contributors
import SwiftUI
/// A transition that blurs, fades and scales a view. Use it as `.transition(.blurFade)`.////// With Reduce Motion on, the view only fades.struct BlurFadeTransition: Transition { var radius: CGFloat = 18 var scale: CGFloat = 0.9
func body(content: Content, phase: TransitionPhase) -> some View { content.modifier(BlurFadeEffect(radius: radius, scale: scale, isIdentity: phase.isIdentity)) }}
extension Transition where Self == BlurFadeTransition { static var blurFade: BlurFadeTransition { BlurFadeTransition() }
static func blurFade(radius: CGFloat, scale: CGFloat = 0.9) -> BlurFadeTransition { BlurFadeTransition(radius: radius, scale: scale) }}
// The effect lives in a view modifier so it can read the environment.private struct BlurFadeEffect: ViewModifier { let radius: CGFloat let scale: CGFloat let isIdentity: Bool
@Environment(\.accessibilityReduceMotion) private var reduceMotion
func body(content: Content) -> some View { content .blur(radius: isIdentity || reduceMotion ? 0 : radius) .scaleEffect(isIdentity || reduceMotion ? 1 : scale) .opacity(isIdentity ? 1 : 0) }}
// MARK: - Demo
struct BlurFadeTransitionDemo: View { @State private var isShown = true
var body: some View { ZStack { LinearGradient(colors: [.black, .indigo], startPoint: .top, endPoint: .bottom) .ignoresSafeArea()
if isShown { VStack(spacing: 14) { Image(systemName: "moon.stars.fill") .font(.largeTitle) .imageScale(.large) .symbolRenderingMode(.hierarchical) .accessibilityHidden(true)
Text("Good night") .font(.system(.largeTitle, design: .rounded, weight: .bold))
Text("Sleep mode starts in ten minutes.") .font(.callout) .opacity(0.8) } .foregroundStyle(.white) .multilineTextAlignment(.center) .padding(36) .frame(maxWidth: .infinity) .background(.white.opacity(0.12), in: .rect(cornerRadius: 32)) .padding(28) .transition(.blurFade) } } .task { while (try? await Task.sleep(for: .seconds(1.3))) != nil { withAnimation(.smooth(duration: 0.6)) { isShown.toggle() } } } }}
#Preview { BlurFadeTransitionDemo()}