.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.

👉 Start your 7-day free trial of Alex today! 👈


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()
                }
           }
        }
    }
}
Next
Next

How to use AI (and Cursor) to improve your iOS skills