I'm looking to blur a view's background but don't want to have to break out into UIKit to accomplish it (eg. a UIVisualEffectView
) I'm digging through docs and got nowhere, seemingly there is no way to live-clip a background and apply effects to it. Am I wrong or looking into it the wrong way?

- 21,796
- 7
- 67
- 74

- 940
- 1
- 6
- 8
9 Answers
1. The Native SwiftUI way:
Just add .blur()
modifier on anything you need to be blurry like:
Image("BG")
.blur(radius: 20)
Note the top and bottom of the view
Note that you can Group
multiple views and blur them together.
2. The Visual Effect View:
You can bring the prefect UIVisualEffectView
from the UIKit:
VisualEffectView(effect: UIBlurEffect(style: .dark))
With this tiny struct:
struct VisualEffectView: UIViewRepresentable {
var effect: UIVisualEffect?
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}
3. iOS 15: Materials
You can use iOS predefined materials with one line code:
.background(.ultraThinMaterial)

- 95,414
- 31
- 268
- 278
-
2This is the most succinct use of Representable that I have seen. Very helpful. – Andrew Duncan May 11 '21 at 00:51
-
there is no way to change the blur color of the `Material` background in SwiftUI - iOS 15 – JAHelia Apr 27 '22 at 14:19
I haven't found a way to achieve that in SwiftUI yet, but you can use UIKit stuff via UIViewRepresentable
protocol.
struct BlurView: UIViewRepresentable {
let style: UIBlurEffect.Style
func makeUIView(context: UIViewRepresentableContext<BlurView>) -> UIView {
let view = UIView(frame: .zero)
view.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: style)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurView, at: 0)
NSLayoutConstraint.activate([
blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
return view
}
func updateUIView(_ uiView: UIView,
context: UIViewRepresentableContext<BlurView>) {
}
}
Demo:
struct ContentView: View {
var body: some View {
NavigationView {
ZStack {
List(1...100) { item in
Rectangle().foregroundColor(Color.pink)
}
.navigationBarTitle(Text("A List"))
ZStack {
BlurView(style: .light)
.frame(width: 300, height: 300)
Text("Hey there, I'm on top of the blur")
}
}
}
}
}
I used ZStack
to put views on top of it.
ZStack {
// List
ZStack {
// Blurred View
// Text
}
}
And ends up looking like this:

- 21,796
- 7
- 67
- 74
-
6This blurs content in a view but I’m looking for for something that allows blurring of underlying content, much like how a UI VisualEffectView or navigationController works whereas you can have an item that blurs the content it overlays and only within the frame of the BlurringView rather than child content of a BlurringView. I suppose more like how BlendMode works. – Sonicjet Jun 16 '19 at 13:02
-
1
-
1
-
When I navigate the page second time the blur views do not appear. Is it because the updateUIView function is empty? – C.Aglar Oct 22 '20 at 18:00
-
This is genius! It works - and if you use style 'systemChromeMaterial', it mimics how the menu bars have blur / transparency. Nice job. – FontFamily Nov 20 '20 at 01:47
-
Is it possible to make the white lines underneath the blurred view more visible? – SmoothPoop69 Jan 12 '21 at 01:33
The simplest way is here by Richard Mullinix:
struct Blur: UIViewRepresentable {
var style: UIBlurEffect.Style = .systemMaterial
func makeUIView(context: Context) -> UIVisualEffectView {
return UIVisualEffectView(effect: UIBlurEffect(style: style))
}
func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
uiView.effect = UIBlurEffect(style: style)
}
}
Then just use it somewhere in your code like background:
//...
MyView()
.background(Blur(style: .systemUltraThinMaterial))
New in iOS 15 , SwiftUI
has a brilliantly simple equivalent to UIVisualEffectView
, that combines ZStack
, the background()
modifier, and a range of built-in materials.
ZStack {
Image("niceLook")
Text("Click me")
.padding()
.background(.thinMaterial)
}
You can adjust the “thickness” of your material – how much of the background content shines through – by using one of several material types. From thinnest to thickest, they are:
.ultraThinMaterial
.thinMaterial
.regularMaterial
.thickMaterial
.ultraThickMaterial

- 98,760
- 8
- 65
- 87
As mentioned by @mojtaba, it's very peculiar to see white shade at top of image when you set resizable()
along with blur().
As simple trick is to raise the Image padding to -ve.
var body: some View {
return
ZStack {
Image("background_2").resizable()
.edgesIgnoringSafeArea(.all)
.blur(radius: 5)
.scaledToFill()
.padding(-20) //Trick: To escape from white patch @top & @bottom
}
}

- 3,728
- 3
- 37
- 60
-
6You can add another parameter to the `.blur` modifier. If you use `.blur(radius: 5, opaque: true)` it should remove that white shade. – Gareth Lewis Apr 24 '21 at 18:11
-
Adding a black color that ignores safe area fixes the white halo effect. – S. Kaan Özkaya Jul 25 '22 at 14:01
I have found an interesting hack to solve this problem. We can use UIVisualEffectView
to make a live "snapshot" of its background. But this "snapshot" will have an applied effect of UIVisualEffectView
. We can avoid applying this effect using UIViewPropertyAnimator
.
I didn't find any side effects of this hack. You can find my solution here: my GitHub Gist
Code
/// A View in which content reflects all behind it
struct BackdropView: UIViewRepresentable {
func makeUIView(context: Context) -> UIVisualEffectView {
let view = UIVisualEffectView()
let blur = UIBlurEffect()
let animator = UIViewPropertyAnimator()
animator.addAnimations { view.effect = blur }
animator.fractionComplete = 0
animator.stopAnimation(false)
animator.finishAnimation(at: .current)
return view
}
func updateUIView(_ uiView: UIVisualEffectView, context: Context) { }
}
/// A transparent View that blurs its background
struct BackdropBlurView: View {
let radius: CGFloat
@ViewBuilder
var body: some View {
BackdropView().blur(radius: radius)
}
}
Usage
ZStack(alignment: .leading) {
Image(systemName: "globe")
.resizable()
.frame(width: 200, height: 200)
.foregroundColor(.accentColor)
.padding()
BackdropBlurView(radius: 6)
.frame(width: 120)
}

- 71
- 1
- 4
-
This is nice because it uses the old `.blur(radius:)`, which gives more control over the amount of blurring than the new material styles. Even the `ultraThinMaterial` blurs quite a bit compared to, say, `.blur(radius:3)`. The normal use of `.blur` is to apply it to the view you want to blur, but the approach here gives you a view that you can insert in a ZStack and blur the contents _underneath_. The other approaches that do this use the new (heavily blurring) materials. – James Toomey Jan 23 '23 at 18:56
@State private var amount: CGFLOAT = 0.0
var body: some View {
VStack{
Image("Car").resizable().blur(radius: amount, opaque: true)
}
}
Using "Opaque: true" with blur function will eliminate white noise

- 152
- 1
- 10
There is a very useful but unfortunately private (thanks Apple) class CABackdropLayer
It draws a copy of the layers below, I found it useful when using blend mode
or filters, It can also be used for blur effect
Code
open class UIBackdropView: UIView {
open override class var layerClass: AnyClass {
NSClassFromString("CABackdropLayer") ?? CALayer.self
}
}
public struct Backdrop: UIViewRepresentable {
public init() {}
public func makeUIView(context: Context) -> UIBackdropView {
UIBackdropView()
}
public func updateUIView(_ uiView: UIBackdropView, context: Context) {}
}
public struct Blur: View {
public var radius: CGFloat
public var opaque: Bool
public init(radius: CGFloat = 3.0, opaque: Bool = false) {
self.radius = radius
self.opaque = opaque
}
public var body: some View {
Backdrop()
.blur(radius: radius, opaque: opaque)
}
}
Usage
struct Example: View {
var body: some View {
ZStack {
YourBelowView()
YourTopView()
.background(Blur())
.background(Color.someColor.opacity(0.4))
}
}
}
Source

- 75
- 4
Sometimes we need a transparent blur effect. Here will be a solution.
struct TransparentBlurView: UIViewRepresentable {
typealias UIViewType = UIVisualEffectView
func makeUIView(context: Context) -> UIVisualEffectView {
let view = UIVisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterialLight))
return view
}
func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
DispatchQueue.main.async {
if let backdropLayer = uiView.layer.sublayers?.first {
backdropLayer.filters?.removeAll(where: { filter in
String(describing: filter) != "gaussianBlur"
})
}
}
}
}

- 5,204
- 3
- 39
- 45