Liquid Glass is the defining look of iOS 26 and 27. Translucent, light-bending surfaces now appear across Apple's own apps. Meanwhile glassmorphism, frosted panels over vivid gradients, is still one of the most popular design trends on Dribbble and in app templates. Expo gives you three packages to build both:
expo-glass-effectfor Apple's native Liquid Glass (iOS 26+).expo-blurfor a frosted blur on iOS and Android.expo-linear-gradientfor the colorful backgrounds that make glass look good.
Install
npx expo install expo-glass-effect expo-blur expo-linear-gradient
All three are included in Expo Go.
Native Liquid Glass with expo-glass-effect
GlassView renders the real system material, the same one used by iOS tab bars and toolbars:
import { StyleSheet, Text } from "react-native"
import { GlassView } from "expo-glass-effect"
export function GlassCard() {
return (
<GlassView style={styles.card} glassEffectStyle="regular">
<Text style={styles.title}>Now playing</Text>
</GlassView>
)
}
const styles = StyleSheet.create({
card: { padding: 20, borderRadius: 28 },
title: { fontSize: 17, fontWeight: "600" },
})
Key props:
glassEffectStylecan be"regular"(default),"clear", or"none". It also takes a config object to animate between styles:{ style: "clear", animate: true, animationDuration: 0.5 }.tintColortints the glass with your brand color.isInteractivemakes the glass react to touch the way system buttons do.colorSchemeforces"light"or"dark"(default"auto").
Merge glass shapes with GlassContainer
GlassContainer lets nearby glass views blend into each other, giving you the "liquid" morphing effect:
import { GlassContainer, GlassView } from "expo-glass-effect"
<GlassContainer spacing={12} style={{ flexDirection: "row", gap: 8 }}>
<GlassView style={{ width: 56, height: 56, borderRadius: 28 }} isInteractive />
<GlassView style={{ width: 56, height: 56, borderRadius: 28 }} isInteractive />
<GlassView style={{ width: 56, height: 56, borderRadius: 28 }} isInteractive />
</GlassContainer>
spacing is the distance at which glass elements start affecting each other.
Liquid Glass rules to follow
- Don't set
opacitybelow 1 on aGlassViewor its parents. Apple advises against it. To fade glass, animate a wrapper's opacity and toggleglassEffectStyleto"none". - Check availability with
isLiquidGlassAvailable(). On unsupported platforms,GlassViewfalls back to a plainView, so plan a fallback style. - Respect Reduce Transparency with
AccessibilityInfo.isReduceTransparencyEnabled(). - Use glass for controls and navigation layers, not for large content areas.
For tab bars, you don't need any of this. Expo Router native tabs get Liquid Glass automatically.
Cross-platform frosted glass with expo-blur
BlurView blurs whatever is behind it. On iOS it works out of the box. On Android (stable since SDK 55) you wrap the content to blur in a BlurTargetView and pass its ref:
import { useRef } from "react"
import { Image, StyleSheet, Text, View } from "react-native"
import { BlurTargetView, BlurView } from "expo-blur"
export function FrostedHeader() {
const targetRef = useRef<View>(null)
return (
<View style={StyleSheet.absoluteFill}>
<BlurTargetView ref={targetRef} style={StyleSheet.absoluteFill}>
<Image source={require("@/assets/hero.jpg")} style={StyleSheet.absoluteFill} />
</BlurTargetView>
<BlurView
blurTarget={targetRef}
intensity={60}
tint="dark"
blurMethod="dimezisBlurViewSdk31Plus"
style={styles.panel}
>
<Text style={styles.text}>Frosted on iOS and Android</Text>
</BlurView>
</View>
)
}
const styles = StyleSheet.create({
panel: { position: "absolute", top: 80, left: 16, right: 16, padding: 20, overflow: "hidden", borderRadius: 24 },
text: { color: "white", fontSize: 18, fontWeight: "600" },
})
Android tips:
dimezisBlurViewSdk31Plususes the efficient RenderNode API on Android 12+ and falls back to a translucent view on older versions. That's the best default.- Multiple
BlurViews can share oneBlurTargetView, which is more efficient than one target each. borderRadiusisn't applied directly. Useoverflow: "hidden".- Render
BlurViewafter dynamic content like lists, or the blur won't update. - Without
blurTarget, Android shows a semi-transparent view instead of a blur.
intensity (1–100) can be animated with Reanimated, so you can ramp blur as a sheet opens.
Gradients: the secret to good glassmorphism
Glass over a flat gray background looks like a dirty window. Glass over a vivid gradient looks premium:
import { LinearGradient } from "expo-linear-gradient"
<LinearGradient
colors={["#7c3aed", "#db2777", "#f59e0b"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
style={StyleSheet.absoluteFill}
/>
Stack a BlurView or GlassView card on top, add a subtle 1px white border at 20–30% opacity, and you have classic glassmorphism.
A progressive enhancement pattern
Use native Liquid Glass where it exists and frosted blur everywhere else:
import { Platform, type ViewProps } from "react-native"
import { GlassView, isLiquidGlassAvailable } from "expo-glass-effect"
import { BlurView } from "expo-blur"
export function Surface(props: ViewProps) {
if (Platform.OS === "ios" && isLiquidGlassAvailable()) {
return <GlassView {...props} />
}
return <BlurView intensity={50} tint="systemMaterial" {...props} />
}
On Android, pass a blurTarget as shown above for a real blur.
Ready-made glass components
- Gradient Background has 14 curated three-stop gradient presets with a flash-free 700ms cross-fade, built on stacked
expo-linear-gradientlayers. - Animated Bottom Navigation includes a Glassmorphism variant with real expo-blur on iOS and Android 12+.
- Native Bottom Sheet has a gaussian-blur backdrop that ramps with sheet position.
All are free and MIT-licensed. For full SwiftUI-level control, including glassEffect() modifiers, see our Expo UI guide.