Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a border in SwiftUI with clipShape?

Tags:

swift

swiftui

I'm confused how I add a border with a stroke color and line width to a SwiftUI View using clipShape. Basically, I just want to have rounded corners with a border color.

Rectangle()
    .frame(width: 80, height: 80)
    .foregroundStyle(.gray)
    .clipShape(
        RoundedRectangle(cornerRadius: 6)
    )
like image 297
Berry Blue Avatar asked Jan 31 '26 22:01

Berry Blue


1 Answers

Applying a border around a clipped shape

Unfortunately, you cannot simply apply .border in combination with .clipShape, because this always draws a square border:

  • If .border is applied before .clipShape then it is clipped at the corners. You notice it more when the corner radius is large.
  • If .border is applied after .clipShape then the corners of the border are square.

So to add a border around a clipped shape, you need to stroke it as a separate operation using the same shape. An overlay works well:

Rectangle()
    .frame(width: 80, height: 80)
    .foregroundStyle(.gray)
    .clipShape(.rect(cornerRadius: 6)) // shorthand for RoundedRectangle(cornerRadius: 6)
    .overlay(
        RoundedRectangle(cornerRadius: 6)
            .stroke(.red, lineWidth: 2)
    )

Corner


A simpler alternative

The question was about using .clipShape. However, if you just want to show a filled shape with a border in the background of a view, it can be done without using .clipShape.

→ Add the shape in the background, fill it with a color or gradient, then stroke its border.

iOS 17+

Since iOS 17, the modifier fill(_:style:) is available. Using this, the shape only needs to be defined once:

HStack {
    // ... foreground content
}
.padding()
.background {
    RoundedRectangle(cornerRadius: 6)
        .fill(.gray)
        .stroke(.red, lineWidth: 2)
}

Pre iOS 17

Pre iOS 17, the border needs to be stroked using a second shape definition, as was being done above with the clip shape. The modifier background(_:in:fillStyle:) can be used for the filled background, to keep the code a bit more compact:

HStack {
    // ... foreground content
}
.padding()
.background(.gray, in: .rect(cornerRadius: 6))
.overlay {
    RoundedRectangle(cornerRadius: 6)
        .stroke(.red, lineWidth: 2)
}

This is not much different to what we had before, except that an unnecessary clip operation is avoided.

like image 152
Benzy Neez Avatar answered Feb 02 '26 13:02

Benzy Neez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!