DEV Community

Cover image for SwiftUI - How to style buttons
Silvia España Gil
Silvia España Gil

Posted on • Updated on

SwiftUI - How to style buttons

Hola Mundo!


Allow me to start with a little bit of context, I'm new at Swift...one month old new at it 🍼👶🏻. And although I love it, it has been a challenge.

Now here it is, first timer Silvia adding her first Button just to find out that the native styling is nonexistent. Is not an exaggeration , loot at it 😞

Screenshot of a native SwiftUI button, white background, blue letters no further styling

I spent at least one hour reading and trying some options until I came with a button that I loved 🥰 - and that you will find later on. So I decided to do this little post with some SwiftUI button styles begginer tips for you to learn, play or use in your own project ✨📱

Let's get on it! 🚀


Tip #1 ☝️


Add this line .buttonStyle(PlainButtonStyle()) after your Button() declaration in order to remove any default style.

As you have seen in the previous screenshot, the native button gives your text a "link" style that you may not like. With this the text colour will reset at your app default.


Tip #2 ✌️


If the label of your button is a text you can initialize it directly writting the String ✏️

Button("I'm a button",
               action: {})
Enter fullscreen mode Exit fullscreen mode

Tip #3 ✨


Use the SF Symbols to add an extra something to your buttons. This native option is not only easy to use but it is also fully customisable and VoiceOver friendly ❤️
Screenshot of a button with an alarm symbol and the text "Remind me"

Button(action: {
            print("Set up alarm")
        }){
            Image(systemName: "alarm")
                .accessibilityLabel("Alarm clock")
            Text("Remind me")
        }
Enter fullscreen mode Exit fullscreen mode

Tip #4 ⭕️


Get to now clipShape(_:style:). When styling your buttons clipShape makes everything easier as it allows you to shape your button in a predetermined figure. Some of the styles accepted in the parameter are rectangle, circle, capsule, ellipse.
Rounded red button with a bell icon

Button(action: {}){
            Image(systemName: "bell")
                .frame(width: 50, height: 50)
                .foregroundColor(Color.black)
                .background(Color.red)
                .clipShape(Circle())
        }.buttonStyle(PlainButtonStyle())
Enter fullscreen mode Exit fullscreen mode

Tip #5 🖐


Use the protocole PrimitiveButtonStyling 🎨. This protocole uses a makeBody function with a configuration we could set.

If we want to create our own CustomStyle, we must start creating a struct that adopts the protocole.

Screenshot of purple button

struct CustomizedStyle: PrimiteButtonStyle {
    typealias Body = Button
    func makeBody(configuration: Configuration) -> some View {
        print(configuration.label)
        configuration.trigger()

        return Button(configuration)
            .background(Color.purple)
            .clipShape(RoundedRectangle(cornerRadius: 10))
            .foregroundColor(Color.white)
    }
}
Enter fullscreen mode Exit fullscreen mode

Our struct will now hold a style that we could use through our app by adding .buttonStyle(CustomizedStyle()) to any Button declaration.

        VStack {
            Button(action: { print("Boom")
            })
            {
                HStack {
                Image(systemName: "bolt")
                Text("Kaboom")
                }
                .padding()
            }
        }.buttonStyle(CustomizedStyle())
Enter fullscreen mode Exit fullscreen mode

Tip #6 💁🏽


There's another protocole you might want to put an eye on and is the ButtonStyle. I know it sounds pretty similar than the #5 and it actually is, however, with this protocole we can customize our button when pressed.
With that being said let's take our previous code and refactor it into the new protocole.

Gif of button that changes colour when clicked

struct CustomizeWithPressed: ButtonStyle {
    typealias Body = Button

    func makeBody(configuration: Self.Configuration) 
-> some View {
        if configuration.isPressed {
            return configuration
                .label
                .padding()
                .background(Color.orange)
                .foregroundColor(Color.white)
                .clipShape(RoundedRectangle(cornerRadius: 10))
        } else {
            return configuration
                .label
                .padding()
                .background(Color.purple)
                .foregroundColor(Color.white)
                .clipShape(RoundedRectangle(cornerRadius: 10))
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

As you can see we now have a conditional inside the makeBody function where we can apply any style we want according to the action.
Finally we only have to call our new style into our button view.

Button("Chamaleon", action:{})
            .buttonStyle(CustomizeWithPressed())
Enter fullscreen mode Exit fullscreen mode

Bonus button 🎉


I guess by now you are really over buttons but, remember then button I told you at the beggining? the culprit of this blog post?

Well I also want to share it because I really liked it, is a white clean classic oval button with a subtle shadow that actually is what draws the button and add up some depth to the view 😌
Screenshot of minimalist button, oval shape, white background, subtle shadows

Button(action: {
            print("Your action function here")
        }){
            Text("Minimalist button")
        }
        //The actual styling
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 25)
                .fill(Color.white)
                .shadow(color: .gray, radius: 2, x: 0, y: 2)
        )
        .buttonStyle(PlainButtonStyle())
Enter fullscreen mode Exit fullscreen mode

Take a look to the code! 👩‍💻

All this buttons codes (and some other) are in this simple repository, don't hesitate to clone or download it.

Discussion (0)