Skip to content

Blur Fade Transition

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

Blur Fade Transition, playing
Download .swift
Origin
Original work
Found by
transition · blur · fade · scale · appear · disappear · custom transition · transición · desenfoque · fundido · escala · aparecer · desaparecer

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() }
}
}
}
}
ParameterTypeDefault
radiusCGFloat18
scaleCGFloat0.9

Copy this code into your project, or download the file.

BlurFadeTransition.swift
// 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()
}