swiftui-liquid-glass

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SwiftUI Liquid Glass

SwiftUI Liquid Glass

Use native Liquid Glass APIs on iOS 26+. Do not recreate the effect with materials, blurs, or shadows.
在iOS 26+上使用原生Liquid Glass API。请勿使用材质、模糊或阴影来重现该效果。

Core rules

核心规则

  1. Don't build custom Liquid Glass through adding backgrounds, outlines, blurs and shadows.
  2. Buttons — style: use
    .buttonStyle(.glass)
    for non-colored buttons, and
    .buttonStyle(.glassProminent)
    for tinted buttons.
    .glassProminent
    supports
    .tint()
    , but this can only be a color (not a gradient).
  3. Buttons — shape: use
    .buttonBorderShape()
    instead of applying a shape to the button label by hand.
  4. Buttons — padding: using this button setup adds roughly 13pt of padding inside the liquid glass shape; keep this in mind when adapting designs.
  5. Custom views: use
    .glassEffect(.regular, in: ...)
    to embed custom Views inside liquid glass containers.
  6. Grouped glass: use
    GlassEffectContainer
    when multiple liquid glass elements are next to each other. this View / Container adds a liquid merge effect when the elements grow / touch each other.
  7. Scrolling: avoid using liquid glass inside ScrollView and List (anything that scrolls).
  8. Bottom bars: when anchoring a liquid glass View to the bottom of the screen, prefer embedding it in
    .safeAreaBar(.bottom)
    instead of a VStack or
    .overlay()
    . safeAreaBar adds a subtle blur effect behind its content.
  9. Toolbar items — no glass: on iOS 26+, navigation bar and window toolbar items get a shared Liquid Glass background by default. For items that should not show the glass capsule (plain icons, custom labels, status text, logos), apply
    .sharedBackgroundVisibility(.hidden)
    on the
    ToolbarItem
    , not on the inner view.
  1. 不要构建自定义Liquid Glass:不要通过添加背景、轮廓、模糊和阴影来实现。
  2. 按钮——样式:非彩色按钮使用
    .buttonStyle(.glass)
    ,带色调按钮使用
    .buttonStyle(.glassProminent)
    .glassProminent
    支持
    .tint()
    ,但仅可传入颜色(不能是渐变)。
  3. 按钮——形状:使用
    .buttonBorderShape()
    ,而非手动给按钮标签应用形状。
  4. 按钮——内边距:使用此按钮设置会在Liquid Glass形状内部添加约13pt的内边距;适配设计时需注意这一点。
  5. 自定义视图:使用
    .glassEffect(.regular, in: ...)
    将自定义视图嵌入Liquid Glass容器中。
  6. 分组玻璃效果:当多个Liquid Glass元素相邻时,使用
    GlassEffectContainer
    。该视图/容器会在元素扩大或接触时添加液体融合效果。
  7. 滚动场景:避免在ScrollView和List(任何可滚动组件)内使用Liquid Glass。
  8. 底部栏:将Liquid Glass视图锚定到屏幕底部时,优先使用
    .safeAreaBar(.bottom)
    嵌入,而非VStack或
    .overlay()
    。safeAreaBar会在其内容后方添加微妙的模糊效果。
  9. 工具栏项目——禁用玻璃效果:在iOS 26+上,导航栏和窗口工具栏项目默认会共享Liquid Glass背景。对于不应显示玻璃胶囊的项目(纯图标、自定义标签、状态文本、Logo),请在**
    ToolbarItem
    **上应用
    .sharedBackgroundVisibility(.hidden)
    ,而非内部视图。

Decision tree

决策树

Need a button?
├─ Neutral / secondary → .buttonStyle(.glass)
└─ Tinted / primary    → .buttonStyle(.glassProminent).tint(someColor)

Need a custom non-button surface (chip, badge, card)?
└─ .glassEffect(.regular, in: shape) on the view content

Multiple glass elements nearby?
└─ Wrap in GlassEffectContainer(spacing: ...) { ... }

Fixed bottom toolbar / action bar?
└─ .safeAreaBar(.bottom) { ... }  — not VStack + overlay

Toolbar item without glass background?
└─ ToolbarItem { ... }.sharedBackgroundVisibility(.hidden)

Inside ScrollView, List, or Form rows?
└─ Do not use Liquid Glass — use solid/material fallback
需要按钮?
├─ 中性/次要按钮 → .buttonStyle(.glass)
└─ 带色调/主要按钮 → .buttonStyle(.glassProminent).tint(someColor)

需要自定义非按钮界面(芯片、徽章、卡片)?
└─ 在视图内容上使用.glassEffect(.regular, in: shape)

多个玻璃效果元素相邻?
└─ 使用GlassEffectContainer(spacing: ...) { ... }包裹

固定底部工具栏/操作栏?
└─ 使用.safeAreaBar(.bottom) { ... } — 而非VStack + overlay

无需玻璃背景的工具栏项目?
└─ ToolbarItem { ... }.sharedBackgroundVisibility(.hidden)

位于ScrollView、List或Form行内?
└─ 不要使用Liquid Glass — 使用纯色/材质作为替代方案

Workflow

工作流程

1) Review existing UI

1) 评审现有UI

  • Flag custom blur/material stacks masquerading as glass.
  • Check buttons use
    .glass
    /
    .glassProminent
    , not hand-built capsules.
  • Confirm
    .buttonBorderShape()
    is used instead of clipping the label.
  • Verify grouped elements sit in
    GlassEffectContainer
    .
  • Flag glass inside scrollable containers.
  • Check bottom-anchored bars use
    .safeAreaBar(.bottom)
    .
  • Check toolbar items that should appear without glass use
    .sharedBackgroundVisibility(.hidden)
    on the
    ToolbarItem
    .
  • Gate with
    #available(iOS 26, *)
    and provide fallbacks.
  • 标记伪装成玻璃效果的自定义模糊/材质堆栈。
  • 检查按钮是否使用
    .glass
    /
    .glassProminent
    ,而非手动构建的胶囊形状。
  • 确认使用
    .buttonBorderShape()
    而非裁剪标签。
  • 验证分组元素是否位于
    GlassEffectContainer
    中。
  • 标记可滚动容器内的玻璃效果。
  • 检查底部锚定栏是否使用
    .safeAreaBar(.bottom)
  • 检查应无玻璃效果的工具栏项目是否在
    ToolbarItem
    上使用
    .sharedBackgroundVisibility(.hidden)
  • 使用
    #available(iOS 26, *)
    做版本判断并提供替代方案。

2) Implement or refactor

2) 实现或重构

  1. Pick the right primitive (button style vs
    glassEffect
    vs
    safeAreaBar
    ).
  2. Apply layout and typography first; add glass modifiers last.
  3. Wrap adjacent glass elements in
    GlassEffectContainer
    .
  4. Account for ~13pt internal button padding when matching designs.
  5. Add iOS 26 availability checks and pre-26 fallbacks.
  1. 选择合适的基础组件(按钮样式 vs
    glassEffect
    vs
    safeAreaBar
    )。
  2. 先应用布局和排版,最后添加玻璃效果修饰符。
  3. 将相邻的玻璃效果元素用
    GlassEffectContainer
    包裹。
  4. 匹配设计时需考虑按钮内部约13pt的内边距。
  5. 添加iOS 26版本检查及iOS 26之前的替代方案。

Patterns

模式示例

Glass buttons

玻璃效果按钮

swift
// Secondary / neutral
Button("Cancel") { dismiss() }
    .buttonStyle(.glass)
    .buttonBorderShape(.capsule)

// Primary / tinted — color only, not gradient
Button("Save") { save() }
    .buttonStyle(.glassProminent)
    .tint(.blue)
    .buttonBorderShape(.roundedRectangle(radius: 12))
Do not clip the label yourself:
swift
// ❌ Wrong — shape on label, not the glass button
Button { action() } label: {
    Text("Save")
        .padding()
        .background(.ultraThinMaterial, in: Capsule())
}

// ✅ Right — native glass handles shape and padding
Button("Save") { action() }
    .buttonStyle(.glassProminent)
    .buttonBorderShape(.capsule)
swift
// 次要/中性按钮
Button("Cancel") { dismiss() }
    .buttonStyle(.glass)
    .buttonBorderShape(.capsule)

// 主要/带色调按钮 — 仅支持颜色,不支持渐变
Button("Save") { save() }
    .buttonStyle(.glassProminent)
    .tint(.blue)
    .buttonBorderShape(.roundedRectangle(radius: 12))
请勿自行裁剪标签:
swift
// ❌ 错误 — 在标签上设置形状,而非玻璃按钮
Button { action() } label: {
    Text("Save")
        .padding()
        .background(.ultraThinMaterial, in: Capsule())
}

// ✅ 正确 — 原生玻璃效果处理形状和内边距
Button("Save") { action() }
    .buttonStyle(.glassProminent)
    .buttonBorderShape(.capsule)

Custom glass surfaces

自定义玻璃效果界面

swift
Label("3 items", systemImage: "tray")
    .padding(.horizontal, 16)
    .padding(.vertical, 10)
    .glassEffect(.regular, in: .capsule)
Add
.interactive()
when the surface responds to touch:
swift
Text("Tap me")
    .padding()
    .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))
swift
Label("3 items", systemImage: "tray")
    .padding(.horizontal, 16)
    .padding(.vertical, 10)
    .glassEffect(.regular, in: .capsule)
当界面需要响应触摸时,添加
.interactive()
swift
Text("Tap me")
    .padding()
    .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))

Grouped glass (merge effect)

分组玻璃效果(融合效果)

swift
GlassEffectContainer(spacing: 24) {
    HStack(spacing: 24) {
        ToolButton(icon: "pencil")
        ToolButton(icon: "eraser")
        ToolButton(icon: "lasso")
    }
}

private struct ToolButton: View {
    let icon: String
    var body: some View {
        Image(systemName: icon)
            .frame(width: 56, height: 56)
            .font(.title2)
            .glassEffect(.regular, in: .circle)
    }
}
Tune
spacing
to control how close elements must be before the liquid merge kicks in.
swift
GlassEffectContainer(spacing: 24) {
    HStack(spacing: 24) {
        ToolButton(icon: "pencil")
        ToolButton(icon: "eraser")
        ToolButton(icon: "lasso")
    }
}

private struct ToolButton: View {
    let icon: String
    var body: some View {
        Image(systemName: icon)
            .frame(width: 56, height: 56)
            .font(.title2)
            .glassEffect(.regular, in: .circle)
    }
}
调整
spacing
参数以控制元素需要靠近到何种程度才会触发液体融合效果。

Bottom action bar

底部操作栏

swift
ContentView()
    .safeAreaBar(.bottom) {
        HStack {
            Button("Share") { share() }
                .buttonStyle(.glass)
            Button("Done") { done() }
                .buttonStyle(.glassProminent)
        }
    }
Prefer this over pinning with
VStack { Spacer(); ... }
or
.overlay(alignment: .bottom)
.
swift
ContentView()
    .safeAreaBar(.bottom) {
        HStack {
            Button("Share") { share() }
                .buttonStyle(.glass)
            Button("Done") { done() }
                .buttonStyle(.glassProminent)
        }
    }
优先使用此方式,而非通过
VStack { Spacer(); ... }
.overlay(alignment: .bottom)
固定。

Toolbar items without glass

无玻璃效果的工具栏项目

On iOS 26+, toolbar items in the same logical grouping share a Liquid Glass background. Hide it when the item should look bare:
swift
.toolbar {
    ToolbarItem(placement: .principal) {
        Text("Draft")
            .font(.headline)
    }
    .sharedBackgroundVisibility(.hidden)

    ToolbarItem(placement: .topBarTrailing) {
        Button { add() } label: {
            Image(systemName: "plus")
        }
    }
    .sharedBackgroundVisibility(.hidden)

    ToolbarItem(placement: .topBarTrailing) {
        Button("Save") { save() }
            .buttonStyle(.glassProminent)
    }
}
Apply
.sharedBackgroundVisibility(.hidden)
on the
ToolbarItem
, not on the
Button
or label inside. Hiding the effect places the item in its own grouping, which can change spacing relative to glass-backed neighbors.
Do not put the modifier on the inner view:
swift
// ❌ Wrong — modifier on Button, glass background remains
ToolbarItem(placement: .topBarTrailing) {
    Button { add() } label: {
        Image(systemName: "plus")
    }
    .sharedBackgroundVisibility(.hidden)
}

// ✅ Right — modifier on ToolbarItem
ToolbarItem(placement: .topBarTrailing) {
    Button { add() } label: {
        Image(systemName: "plus")
    }
}
.sharedBackgroundVisibility(.hidden)
在iOS 26+上,同一逻辑分组内的工具栏项目会共享Liquid Glass背景。当项目需要显示为无背景时,隐藏该效果:
swift
.toolbar {
    ToolbarItem(placement: .principal) {
        Text("Draft")
            .font(.headline)
    }
    .sharedBackgroundVisibility(.hidden)

    ToolbarItem(placement: .topBarTrailing) {
        Button { add() } label: {
            Image(systemName: "plus")
        }
    }
    .sharedBackgroundVisibility(.hidden)

    ToolbarItem(placement: .topBarTrailing) {
        Button("Save") { save() }
            .buttonStyle(.glassProminent)
    }
}
.sharedBackgroundVisibility(.hidden)
应用在**
ToolbarItem
**上,而非内部的Button或标签。隐藏效果会将项目置于单独分组,这可能会改变其与带玻璃效果相邻项目的间距。
请勿将修饰符应用在内部视图上:
swift
// ❌ 错误 — 修饰符应用在Button上,玻璃背景仍会显示
ToolbarItem(placement: .topBarTrailing) {
    Button { add() } label: {
        Image(systemName: "plus")
    }
    .sharedBackgroundVisibility(.hidden)
}

// ✅ 正确 — 修饰符应用在ToolbarItem上
ToolbarItem(placement: .topBarTrailing) {
    Button { add() } label: {
        Image(systemName: "plus")
    }
}
.sharedBackgroundVisibility(.hidden)

Availability fallback

版本兼容替代方案

swift
if #available(iOS 26, *) {
    content.glassEffect(.regular, in: .rect(cornerRadius: 16))
} else {
    content.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}
swift
if #available(iOS 26, *) {
    content.glassEffect(.regular, in: .rect(cornerRadius: 16))
} else {
    content.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}

Anti-patterns

反模式

Anti-patternWhy it failsDo instead
.background(.ultraThinMaterial)
+ blur + stroke + shadow
Not Liquid Glass; wrong optics and no merge/morph
.glassEffect(...)
or button styles
Gradient
.tint()
on
.glassProminent
API accepts color onlySolid
Color
tint, or custom label without glassProminent tint
Glass on
List
/
ScrollView
rows
Scroll + glass = visual glitches, perf costOpaque/material rows; glass only on fixed chrome
Shape applied to button labelMisses native padding (~13pt) and border rendering
.buttonBorderShape()
Bottom bar via
.overlay
No system blur bar treatment
.safeAreaBar(.bottom)
Multiple glass views without containerNo merge effect, worse rendering
GlassEffectContainer
Glass capsule on toolbar items that should be bareiOS 26 adds shared glass to toolbar groupings by default
.sharedBackgroundVisibility(.hidden)
on the
ToolbarItem
.sharedBackgroundVisibility
on inner view
Does not remove toolbar glass backgroundApply on
ToolbarItem
(or other
ToolbarContent
)
反模式失败原因正确做法
.background(.ultraThinMaterial)
+ 模糊 + 描边 + 阴影
并非Liquid Glass;视觉效果错误且无融合/变形效果使用
.glassEffect(...)
或按钮样式
.glassProminent
设置渐变
.tint()
API仅接受颜色使用纯色
Color
作为色调,或不使用glassProminent色调的自定义标签
List
/
ScrollView
行上使用玻璃效果
滚动+玻璃效果会导致视觉故障,且影响性能使用不透明/材质行;仅在固定界面元素上使用玻璃效果
给按钮标签应用形状缺少原生内边距(约13pt)和边框渲染使用
.buttonBorderShape()
通过
.overlay
实现底部栏
无系统模糊栏处理使用
.safeAreaBar(.bottom)
多个玻璃视图未使用容器包裹无融合效果,渲染效果更差使用
GlassEffectContainer
不应显示玻璃胶囊的工具栏项目出现玻璃效果iOS 26默认给工具栏分组添加共享玻璃效果
ToolbarItem
上使用
.sharedBackgroundVisibility(.hidden)
.sharedBackgroundVisibility
应用在内部视图上
无法移除工具栏玻璃背景应用在
ToolbarItem
(或其他
ToolbarContent
)上

Review checklist

评审检查清单

  • No hand-rolled blur/material glass imitations
  • Buttons use
    .glass
    or
    .glassProminent
    with
    .buttonBorderShape()
  • Design spacing accounts for ~13pt internal button padding
  • Custom surfaces use
    .glassEffect(.regular, in: ...)
  • Adjacent glass wrapped in
    GlassEffectContainer
  • No glass inside scroll views
  • Bottom chrome uses
    .safeAreaBar(.bottom)
  • Toolbar items without glass use
    .sharedBackgroundVisibility(.hidden)
    on
    ToolbarItem
  • #available(iOS 26, *)
    with fallback on older OS
  • 无手动实现的模糊/材质玻璃仿制品
  • 按钮使用
    .glass
    .glassProminent
    并搭配
    .buttonBorderShape()
  • 设计间距考虑了按钮内部约13pt的内边距
  • 自定义界面使用
    .glassEffect(.regular, in: ...)
  • 相邻玻璃效果元素用
    GlassEffectContainer
    包裹
  • 滚动视图内无玻璃效果
  • 底部界面元素使用
    .safeAreaBar(.bottom)
  • 无玻璃效果的工具栏项目在
    ToolbarItem
    上使用
    .sharedBackgroundVisibility(.hidden)
  • 使用
    #available(iOS 26, *)
    并为旧系统提供替代方案

Additional resources

额外资源