.animation() vs withAnimation(): what's the difference?
You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿
Advertisement
Make iOS Apps using AI, with Alex Sidebar
Take advantage of our coding agent, built specifically for Swift. Generate modern SwiftUI from images. Fast Apply suggestions from Claude 3.5 Sonnet, o3-mini, and DeepSeek. Autofix errors and warnings. Enable thinking and web search. And so much more.
Sponsors like Alex Sidebar really help me grow my content creation, so if you have time please make sure to check out their survey: it’s a direct support to my content creation ☺️
In SwiftUI, there are two ways to trigger animations.
You can either attach the modifier .animation()
to a view or wrap some code in the function withAnimation()
.
But what’s the difference between these two approaches?
And when should you use one versus the other?
That’s what I want to explain in this article!
I’ve created two views and a button that toggles their width
between 100
and 200
.
For now, when I tap on the button, the width
changes without any animations:
Let’s add the modifier .animation()
on the first view and see what happens:
As we can see, now the change in width
gets animated for the first view.
This illustrates how the .animation()
modifier works: it allows us to declare a scoped animation that will only apply to the view to which it’s been attached.
Now let’s talk about the function withAnimation()
.
We’ve seen that the modifier .animation()
allows us to declare scoped animations.
However, there are situations where we need the opposite: we want to update some state and animate everything that depends on that state that can be animated.
This is exactly what withAnimation()
does: if we use it to wrap the code that updates the state of the views, then we see that both views now animate their change in width
.
So that’s the difference between the modifier .animation()
and the function withAnimation()
: the modifier allows us to create locally scoped animations whereas the function allows us to create global animations.
At this point you might be wondering: what if I want to make sure that a view doesn’t get animated by the function withAnimation()
?
That’s actually possible!
The way to do it is to use the modifier .transaction()
to remove any animation that would be about to be executed, and the view will be opted-out from global animations:
That’s all for this article!
I hope that the difference between .animation()
and withAnimation()
has now become clearer 😌
Here’s the code if you want to experiment with it:
// Using .animation()
import SwiftUI
struct ContentView: View {
@State var smallViews = true
var body: some View {
VStack {
Rectangle()
.fill(.blue)
.frame(width: smallViews ? 100 : 200, height: 100)
.animation(.default, value: smallViews)
Rectangle()
.fill(.red)
.frame(width: smallViews ? 100 : 200, height: 100)
Button("Small / Large") {
smallViews.toggle()
}
}
}
}
// using withAnimation
import SwiftUI
struct ContentView: View {
@State var smallViews = true
var body: some View {
VStack {
Rectangle()
.fill(.blue)
.frame(width: smallViews ? 100 : 200, height: 100)
Rectangle()
.fill(.red)
.frame(width: smallViews ? 100 : 200, height: 100)
Button("Small / Large") {
withAnimation(.default) {
smallViews.toggle()
}
}
}
}
}
// Using .transaction()
import SwiftUI
struct ContentView: View {
@State var smallViews = true
var body: some View {
VStack {
Rectangle()
.fill(.blue)
.frame(width: smallViews ? 100 : 200, height: 100)
Rectangle()
.fill(.red)
.frame(width: smallViews ? 100 : 200, height: 100)
.transaction { transaction in
transaction.animation = nil
}
Button("Small / Large") {
withAnimation(.default) {
smallViews.toggle()
}
}
}
}
}