Designing customized UI with Liquid Glass on iOS 26 – Donny Wals


Printed on: July 1, 2025
Up to date on: July 10, 2025

Liquid Glass is iOS 26’s new design language. Which means that loads of apps will likely be adopting a brand new UI philosophy that may require some important modifications to the way you’re designing your app’s UI.

In the event you’re not able to undertake Liquid Glass simply but, Apple has supplied you an escape hatch that ought to be usable till the subsequent main iOS launch.

I just lately explored updating my exercise app Maxine to work effectively with Liquid Glass tab bars which you’ll be taught extra about right here.

On this publish, I’d prefer to discover how we will construct customized Liquid Glass elements for our apps operating on iOS 26 and its siblings. We’ll begin off by exploring when Liquid Glass is acceptable after which transfer on to take a look at SwiftUI’s Liquid Glass associated view modifiers.

By the top of this publish, we’ll have constructed the UI that you may see in motion under (video slowed down for dramatic impact):

In the event you desire studying by video, you’ll be able to check out this publish on YouTube

When do you have to use Liquid Glass

The concept of Liquid Glass is that it acts as a layer on prime of your app’s UI. In apply this can normally imply that your principal app content material isn’t constructed utilizing the glass model. Doing so would lead to some fairly dangerous wanting UI as you’ll be able to see on this video:

On this video, I utilized a glass impact to all of my listing rows. The result’s a brilliant bizarre interface that overuses Liquid Glass.

As a substitute, Liquid Glass ought to be utilized to components that sit on prime of your UI. Examples embrace toolbars, tab bars, floating motion buttons and comparable elements.

An instance of this may be seen proper right here in Maxine:

The default tab bar is a Liquid Glass element that overlays my listing. The floating plus button additionally has a glass impact utilized to it though you’ll be able to barely see it because of the gentle background.

The purpose is that Liquid Glass components ought to at all times be designed as sitting “on prime” of one thing. They don’t stack, they’re not a part of your principal UI, they’re at all times on their very own layer whenever you’re designing.

Now, I’m not a designer. So should you can provide you with a good way to make use of Liquid Glass that locations a component in your principal content material. I’m not going to let you know that you may’t or shouldn’t; you most likely know significantly better than I do. That mentioned, Apple’s philosophy for Liquid Glass is a layered design so for security you must most likely keep on with that.

Making use of a Liquid Glass impact to UI components

Let’s construct out a pleasant UI factor that may actually profit from a Liquid Glass appear and feel. It’s a UI factor that existed in an app known as Path which now not exists, and the UI factor hasn’t actually been used a lot since. That mentioned, I just like the interplay and I feel it’ll be enjoyable to present it a glass overhaul.

Our Start line

You’ll be able to see an instance of the button and its UI proper right here:

It takes fairly some code to attain this impact, and most of it isn’t related to Liquid Glass. That’s why you’ll be able to check out the ultimate code proper right here on GitHub. There’s a department for the start line in addition to the top outcome (principal) so you’ll be able to mess around a bit should you’d like.

The view itself appears to be like like this:

struct ContentView: View {
    @State non-public var isExpanded = false
    var physique: some View {
        ZStack(alignment: .bottomTrailing) {
            Colour
                .clear
                .overlay(
                    Picture("bg_img")
                        .resizable()
                        .scaledToFill()
                        .edgesIgnoringSafeArea(.all)
                )

            button(kind: .residence)
            button(kind: .write)
            button(kind: .chat)
            button(kind: .e mail)

            Button {
                withAnimation {
                    isExpanded.toggle()
                }
            } label: {
                Label("House", systemImage: "listing.bullet")
                    .labelStyle(.iconOnly)
                    .body(width: 50, peak: 50)
                    .background(Circle().fill(.purple))
                    .foregroundColor(.white)
            }.padding(32)
        }
    }

    non-public func button(kind: ButtonType) -> some View {
        return Button {} label: {
            Label(kind.label, systemImage: kind.systemImage)
                .labelStyle(.iconOnly)
                .body(width: 50, peak:50)
                .background(Circle().fill(.white))
        }
        .padding(32)
        .offset(kind.offset(expanded: isExpanded)
        .animation(.spring(period: kind.period, bounce: 0.2))
    }
}

This view by itself isn’t all that fascinating, it accommodates a few buttons, and making use of a liquid glass impact to our buttons shouldn’t be too laborious.

Making use of a glass impact

To make buttons appear like Liquid Glass, you apply the glassEffect view modifier to them:

Button {
    withAnimation {
        isExpanded.toggle()
    }
} label: {
    Label("House", systemImage: "listing.bullet")
        .labelStyle(.iconOnly)
        .body(width: 50, peak: 50)
        .background(Circle().fill(.purple))
        .foregroundColor(.white)
}
.glassEffect()
.padding(32)

After making use of the liquidGlass modifier to all buttons the app appears to be like like this whenever you run it:

We’re not seeing a glass impact in any respect!

That’s as a result of we additionally set a background on our buttons, so let’s go forward and take away the background to see what our view appears to be like like:

Button {
    withAnimation {
        isExpanded.toggle()
    }
} label: {
    Label("House", systemImage: "listing.bullet")
        .labelStyle(.iconOnly)
        .body(width: 50, peak: 50)
        .foregroundColor(.white)
}
.glassEffect()
.padding(32)

If we run the app now, our UI appears to be like like this:

Our icons are a bit laborious to learn and I’m truthfully not precisely certain whether or not this can be a beta bug or whether or not it’s imagined to be this manner.

Notice that Button additionally comes with a .glass button model that you need to use. This impact is barely completely different from what I’ve used right here however I discover that the button model doesn’t at all times enable for the sorts of customizations that I like.

You’ll be able to apply the glass button model as follows:

Button {
    withAnimation {
        isExpanded.toggle()
    }
} label: {
    Label("House", systemImage: "listing.bullet")
        .labelStyle(.iconOnly)
        .body(width: 50, peak: 50)
        .foregroundColor(.white)
}
.buttonStyle(.glass)
.padding(32)

That mentioned, there are two issues I’d love to do at this level:

  1. Apply a background tint to the buttons
  2. Make the buttons seem interactive

Let’s begin with the background shade.

Making use of a background shade to our glass impact

To model our buttons with a background shade, we have to tint our glass. Right here’s how we will try this:

Button {
    withAnimation {
        isExpanded.toggle()
    }
} label: {
    Label("House", systemImage: "listing.bullet")
        .labelStyle(.iconOnly)
        .body(width: 50, peak: 50)
        .foregroundColor(.white)
}
.glassEffect(.common.tint(.purple))
.padding(32)

This already appears to be like loads higher:

Discover that the buttons nonetheless have a round form though we’re not explicitly drawing a circle background. That’s the default model for elements that you just apply a glassEffect to. You’ll at all times get a form that has rounded corners that match properly with the remainder of your app’s UI and the context the place the impact is utilized.

I do really feel like my buttons are a bit too opaque, so let’s apply a little bit of opacity to our tint shade to get extra of a see-through impact:

Button {
    withAnimation {
        isExpanded.toggle()
    }
} label: {
    Label("House", systemImage: "listing.bullet")
        .labelStyle(.iconOnly)
        .body(width: 50, peak: 50)
        .foregroundColor(.white)
}
.glassEffect(.common.tint(.purple.opacity(0.8))
.padding(32)

That is what our view appears to be like like now:

Once I faucet the buttons now, not loads occurs as proven within the video above. We will do higher by making our buttons reply to consumer interplay.

Making an interactive glass impact

To make our glass buttons reply to consumer enter by rising a bit and making use of a form of shimmer impact, we apply the interactive modifier to the glass impact:

Button {
    withAnimation {
        isExpanded.toggle()
    }
} label: {
    Label("House", systemImage: "listing.bullet")
        .labelStyle(.iconOnly)
        .body(width: 50, peak: 50)
        .foregroundColor(.white)
}
.glassEffect(.common.tint(.purple.opacity(0.8).interactive())
.padding(32)

That is what our interactions appear like now:

Our UI is coming collectively. With the glassEffect view modifier, the interactive modifier and a tint we managed to construct a fairly compelling impact.

Nonetheless, our UI isn’t fairly liquid. You’re taking a look at distinct buttons performing an impact.

We will group our components collectively to make it seem as if they’re all coming from the identical drop of glass.

This sounds a bit bizarre so let’s simply bounce into an instance instantly.

Grouping Liquid Glass components collectively

The very first thing we should always do now that now we have a bunch of components which might be all utilizing a Liquid Glass impact is group them collectively in a container. It is a advice from Apple that helps be sure the system can render our results effectively. It additionally makes it in order that Liquid Glass components which might be shut collectively will begin to mix into one another. This makes it appear like they’re all merging and seperating as they transfer across the display screen.

GlassEffectContainer {
    button(kind: .residence)
    button(kind: .write)
    button(kind: .chat)
    button(kind: .e mail)

    Button {
        withAnimation {
            isExpanded.toggle()
        }
    } label: {
        Label("House", systemImage: "listing.bullet")
            .labelStyle(.iconOnly)
            .body(width: 50, peak: 50)
            .foregroundColor(.white)
    }
    .glassEffect(.common.tint(.purple.opacity(0.8)).interactive())
    .padding(32)
}

By inserting our Liquid Glass UI components in the identical container, the weather will mix collectively after they’re shut to one another within the UI. For instance, once we place all buttons in an HStack with no spacing, they find yourself wanting like this:

As a result of all the weather are in the identical GlassEffectContainer, we will now run our animation and have the buttons animate in a fluid method:

I’ve slowed all the things down a bit so you’ll be able to benefit from the impact and see that the elements all originate from a single button, making them appear like a liquid.

The maths to attain all that is a part of the ButtonType enum within the GitHub repository that you may try if you wish to see precisely how the top outcome was achieved.

In Abstract

Liquid glass may not be your factor and that’s completely advantageous. That mentioned, it permits us to experiment with UI in enjoyable ways in which would possibly shock you.

On this publish, you discovered concerning the glassEffect modifier in addition to the glassEffectID view modifier to construct a enjoyable menu element that may present and conceal itself utilizing a enjoyable, fluid animation.

If you wish to see the top outcome or use this code, be happy to drag it from GitHub and modify it to fit your wants.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles