Liquid Glass is iOS 26’s new design language. Which means that a whole lot of apps will probably be adopting a brand new UI philosophy that may require some vital 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 properly with Liquid Glass tab bars which you’ll be able to be taught extra about right here.
On this submit, I’d wish to discover how we will construct customized Liquid Glass elements for our apps working 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 submit, we’ll have constructed the UI that you would be able to see in motion under (video slowed down for dramatic impact):
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 follow this may normally imply that your fundamental app content material isn’t constructed utilizing the glass model. Doing so would end in some fairly dangerous wanting UI as you may see on this video:
On this video, I utilized a glass impact to all of my record rows. The result’s a brilliant bizarre interface that overuses Liquid Glass.
As an alternative, 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 part that overlays my record. The floating plus button additionally has a glass impact utilized to it despite the fact that you may barely see it because of the mild background.
The purpose is that Liquid Glass components ought to all the time be designed as sitting “on prime” of one thing. They don’t stack, they’re not a part of your fundamental UI, they’re all the time on their very own layer while you’re designing.
Now, I’m not a designer. So in the event you can provide you with a good way to make use of Liquid Glass that locations a component in your fundamental content material. I’m not going to let you know that you would be able to’t or shouldn’t; you in all probability know a lot better than I do. That mentioned, Apple’s philosophy for Liquid Glass is a layered design so for security it is best to in all probability follow that.
Making use of a Liquid Glass impact to UI components
Let’s construct out a pleasant UI aspect that may actually profit from a Liquid Glass feel and look. It’s a UI aspect that existed in an app referred to as Path which now not exists, and the UI aspect hasn’t actually been used a lot since. That mentioned, I just like the interplay and I believe it’ll be enjoyable to present it a glass overhaul.
Our Place to begin
You’ll be able to see an instance of the button and its UI proper right here:
It takes fairly some code to realize this impact, and most of it isn’t related to Liquid Glass. That’s why you may check out the ultimate code proper right here on GitHub. There’s a department for the start line in addition to the top outcome (fundamental) so you may mess around a bit in the event you’d like.
The view itself seems like this:
struct ContentView: View {
@State personal var isExpanded = false
var physique: some View {
ZStack(alignment: .bottomTrailing) {
Colour
.clear
.overlay(
Picture("bg_img")
.resizable()
.scaledToFill()
.edgesIgnoringSafeArea(.all)
)
button(sort: .residence)
button(sort: .write)
button(sort: .chat)
button(sort: .e-mail)
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.background(Circle().fill(.purple))
.foregroundColor(.white)
}.padding(32)
}
}
personal func button(sort: ButtonType) -> some View {
return Button {} label: {
Label(sort.label, systemImage: sort.systemImage)
.labelStyle(.iconOnly)
.body(width: 50, top:50)
.background(Circle().fill(.white))
}
.padding(32)
.offset(isExpanded ? sort.offset : .zero)
.animation(.spring(length: sort.length, bounce: 0.2))
}
}
This view by itself isn’t all that attention-grabbing, it accommodates a few buttons, and making use of a liquid glass impact to our buttons shouldn’t be too exhausting.
Making use of a glass impact
To make buttons appear to be Liquid Glass, you apply the glassEffect
view modifier to them:
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.background(Circle().fill(.purple))
.foregroundColor(.white)
}
.glassEffect()
.padding(32)
After making use of the liquidGlass
modifier to all buttons the app seems like this while 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 seems like:
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.foregroundColor(.white)
}
.glassEffect()
.padding(32)
If we run the app now, our UI seems like this:
Our icons are a bit exhausting to learn and I’m truthfully not precisely positive whether or not this can be a beta bug or whether or not it’s alleged to be this fashion.
Word that Button
additionally comes with a .glass
button model that you should use. This impact is barely totally different from what I’ve used right here however I discover that the button model doesn’t all the time 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("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.foregroundColor(.white)
}
.buttonStyle(.glass)
.padding(32)
That mentioned, there are two issues I’d love to do at this level:
- Apply a background tint to the buttons
- Make the buttons seem interactive
Let’s begin with the background coloration.
Making use of a background coloration to our glass impact
To model our buttons with a background coloration, we have to tint our glass. Right here’s how we will do this:
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.foregroundColor(.white)
}
.glassEffect(.common.tint(.purple))
.padding(32)
This already seems so much higher:
Discover that the buttons nonetheless have a round form despite the fact that we’re not explicitly drawing a circle background. That’s the default model for elements that you simply apply a glassEffect
to. You’ll all the time 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 coloration to get extra of a see-through impact:
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.foregroundColor(.white)
}
.glassEffect(.common.tint(.purple.opacity(0.8))
.padding(32)
That is what our view seems like now:
After I faucet the buttons now, not so much 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 type of shimmer impact, we apply the interactive
modifier to the glass impact:
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.foregroundColor(.white)
}
.glassEffect(.common.tint(.purple.opacity(0.8).interactive())
.padding(32)
That is what our interactions appear to be now:
Our UI is coming collectively. With the glassEffect
view modifier, the interactive
modifier and a tint
we managed to construct a reasonably compelling impact.
Nevertheless, our UI isn’t fairly liquid. You’re 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 straight away.
Grouping Liquid Glass components collectively
The very first thing we should always do now that we have now a bunch of components which might be all utilizing a Liquid Glass impact is group them collectively in a container. It is a suggestion from Apple that helps be sure that 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 to be they’re all merging and seperating as they transfer across the display screen.
GlassEffectContainer {
button(sort: .residence)
button(sort: .write)
button(sort: .chat)
button(sort: .e-mail)
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Label("Dwelling", systemImage: "record.bullet")
.labelStyle(.iconOnly)
.body(width: 50, top: 50)
.foregroundColor(.white)
}
.glassEffect(.common.tint(.purple.opacity(0.8)).interactive())
.padding(32)
}
By putting 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 every part down a bit so you may benefit from the impact and see that the elements all originate from a single button, making them appear to be a liquid.
The mathematics to realize all that is a part of the ButtonType
enum within the GitHub repository that you would be able to take a look at 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 high-quality. That mentioned, it permits us to experiment with UI in enjoyable ways in which may shock you.
On this submit, you realized concerning the glassEffect
modifier in addition to the glassEffectID
view modifier to construct a enjoyable menu part 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.