How it works
ButtonStyle is a protocol that lets you define a reusable appearance and interaction behavior for buttons, then apply it consistently throughout your app. Instead of attaching the same chain of modifiers to every Button, you describe the styling once in a type that conforms to ButtonStyle and hand it to the buttonStyle(_:) modifier. SwiftUI calls into your style to build each button's body, passing along the button's label and its current pressed state. Reach for ButtonStyle whenever you want a custom button look that responds to user interaction and stays consistent across many call sites.
Conform a type to ButtonStyle
A button style is any type that adopts the
ButtonStyleprotocol; typically a smallstructso it stays lightweight and value-based. HereGradientButtonStyledeclares conformance withstruct GradientButtonStyle: ButtonStyle, giving you a named, reusable style you can apply to any button.Implement makeBody(configuration:)
The single required method,
makeBody(configuration:), returns the view that represents the styled button. SwiftUI invokes it to render the button, and you returnsome Viewdescribing the final appearance — in this case the label wrapped in padding, a gradient background, and a capsule shape.Compose around configuration.label
The
configurationparameter (of the associatedConfigurationtype) carriesconfiguration.label, a type-erased view representing the button's title or content. You build your style by decorating it: the example takesconfiguration.labeland chains.padding,.backgroundwith aLinearGradient,.foregroundStyle(.white), and.clipShape(Capsule()).React to configuration.isPressed
configuration.isPressedreports whether the user is currently pressing the button, letting your style provide interactive feedback. The example reads it to shrink the button while held with.scaleEffect(configuration.isPressed ? 0.95 : 1), so the press state visibly drives the appearance.Apply the style with buttonStyle(_:)
You attach a custom style by passing an instance to the
buttonStyle(_:)modifier, which also propagates down to descendant buttons in the view hierarchy. The example wires up its style with.buttonStyle(GradientButtonStyle())on theButton("Get Started"), replacing the system look with the gradient capsule.
0.95 in .scaleEffect(configuration.isPressed ? 0.95 : 1) to 1.1 so the button grows instead of shrinking on press, revealing how configuration.isPressed drives the style's interactive feedback.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct ButtonStyleDemo: View {
struct GradientButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(.horizontal, 24)
.padding(.vertical, 12)
.background(
LinearGradient(
colors: [.purple, .blue],
startPoint: .leading,
endPoint: .trailing
)
)
.foregroundStyle(.white)
.clipShape(Capsule())
.scaleEffect(configuration.isPressed ? 0.95 : 1)
}
}
var body: some View {
Button("Get Started") { }
.buttonStyle(GradientButtonStyle())
.padding()
}
}