Advanced SwiftUI button styling and animation

Learn how to style SwiftUI buttons using ButtonStyle protocol and .buttonStyle() modifier by creating reusable button styles. Using ButtonStyle protocol allows you to create advanced button styles and introduce animations to the button style when it is being pressed.

Let’s start with a simple button:

Button(action: {
    print("Button action")
}) {
    HStack {
        Image(systemName: "bookmark.fill")
        Text("Bookmark")
    }
}
Basic SwiftUI button
Basic SwiftUI button

Now, let’s create new struct called GradientButtonStyle which implements the ButtonStyle protocol and applies a gradient to the button’s design/background color:

struct GradientButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(Color.white)
            .padding()
            .background(LinearGradient(gradient: Gradient(colors: [Color.red, Color.orange]), startPoint: .leading, endPoint: .trailing))
            .cornerRadius(15.0)
    }
}

And apply the new style via the .buttonStyle() modifier on the button:

Button(action: {
    print("Button action")
}) {
    HStack {
        Image(systemName: "bookmark.fill")
        Text("Bookmark")
    }
}.buttonStyle(GradientButtonStyle())
SwiftUI button with gradient background
SwiftUI button with gradient background

The configuration object available inside of the makeBody method contains a label and an isPressed instance properties. The label property gives you access to button’s label view which you can modify with desired modifiers. The isPressed property gives you insight into whether the button is actually pressed or not.

In order to animate the size of a button when it’s pressed, we’re going to use the .scaleEffect() modifier in combination with the isPressed property by changing the scale based on the isPressed value:

.scaleEffect(configuration.isPressed ? 1.3 : 1.0)
Scaled SwiftUI button when pressed
Scaled SwiftUI button when pressed

New GradientButtonStyle struct which also animates the size of the button now looks like that:

struct GradientButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(Color.white)
            .padding()
            .background(LinearGradient(gradient: Gradient(colors: [Color.red, Color.orange]), startPoint: .leading, endPoint: .trailing))
            .cornerRadius(15.0)
            .scaleEffect(configuration.isPressed ? 1.3 : 1.0)
    }
}

Following a similar pattern, you can change the background color of a button when it’s pressed:

.background(configuration.isPressed ? Color.green : Color.yellow)
Animated SwiftUI button background color
Animated SwiftUI button background color

Related tutorials: