Shipnative
ShipNativeShipNative
Sign inStart building
GuideOctober 2026 · 8 min read

Expo Blur: BlurView on iOS and Android

A blurred tab bar or a frosted card is one of the quickest ways to make a React Native app feel like it belongs on iOS. expo-blur gives you that in one component, and on an iPhone it works the first time. Then you open the same screen on Android and get a flat grey rectangle. That is expected behaviour, not a bug, and the fix needs a little setup. This guide covers the basics, the Android setup, blurred tab bars and headers, and the two layout traps that make a blur look wrong.

The basic BlurView

npx expo install expo-blur
import { BlurView } from 'expo-blur';
import { ImageBackground, StyleSheet, Text } from 'react-native';

export default function FrostedCard() {
  return (
    <ImageBackground source={require('./photo.jpg')} style={styles.bg}>
      <BlurView intensity={60} tint="dark" style={styles.card}>
        <Text style={styles.title}>Golden hour</Text>
        <Text style={styles.meta}>Lisbon · 12 photos</Text>
      </BlurView>
    </ImageBackground>
  );
}

const styles = StyleSheet.create({
  bg: { flex: 1, justifyContent: 'flex-end', padding: 16 },
  card: {
    padding: 20,
    borderRadius: 20,
    overflow: 'hidden',   // without this the corners stay square
  },
  title: { color: '#fff', fontSize: 20, fontWeight: '600' },
  meta: { color: 'rgba(255,255,255,0.7)', marginTop: 4 },
});

intensity runs from 1 to 100 and defaults to 50. tint adds a translucent colour layer on top of the blur: light, dark, default, and on iOS the system materials such as systemThinMaterialthat match Apple’s own controls. There is no tint that renders the blur alone, so if a dark tint looks muddy, lower the intensity rather than hunting for a “none” option. Children of the BlurView render sharp on top of the blur, which is why the text above stays readable.

Why Android shows a flat tint, and the fix

iOSAndroidWeb
Real blur by default✅ Yes❌ Semi-transparent view✅ backdrop-filter
Needs BlurTargetViewNoYes, for a real blurNo
blurMethod propIgnorednone, dimezisBlurView, dimezisBlurViewSdk31PlusIgnored
Performance costLowHigher, best on Android 12+Browser dependent
Expo Go✅ Yes✅ Yesn/a

iOS has a system blur that any view can use cheaply. Android does not, so expo-blur ships a blur implementation that is off by default and renders a semi-transparent view instead. To turn it on, mark the content that should be blurred with BlurTargetView and point the BlurView at it:

import { useRef } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { BlurTargetView, BlurView } from 'expo-blur';

export default function Screen({ children }) {
  const targetRef = useRef<View | null>(null);

  return (
    <View style={{ flex: 1 }}>
      <BlurTargetView ref={targetRef} style={StyleSheet.absoluteFill}>
        {children}
      </BlurTargetView>

      <BlurView
        blurTarget={targetRef}          // Android: what to blur
        blurMethod="dimezisBlurViewSdk31Plus"
        intensity={70}
        tint="dark"
        style={styles.bar}
      >
        <Text style={{ color: '#fff' }}>Now playing</Text>
      </BlurView>
    </View>
  );
}

const styles = StyleSheet.create({
  bar: { position: 'absolute', left: 16, right: 16, bottom: 32, padding: 16, borderRadius: 16, overflow: 'hidden' },
});

dimezisBlurViewSdk31Plus uses the real blur on Android 12 and newer and falls back to the tint on older devices, which avoids a noticeable performance hit on old phones. dimezisBlurView blurs everywhere at that cost. iOS ignores both props, so the same code is safe on both platforms. If you are on an older Expo SDK, the prop was called experimentalBlurMethod and there was no BlurTargetView, so check the docs for the SDK version in your package.json before copying examples.

Blurred tab bars and headers

The most common use of expo-blur is a translucent tab bar that content scrolls under. With Expo Router or React Navigation bottom tabs, the bar has to be absolutely positioned so content can pass behind it, and the blur goes in tabBarBackground:

import { Tabs } from 'expo-router';
import { BlurView } from 'expo-blur';
import { Platform, StyleSheet, View } from 'react-native';

export default function TabLayout() {
  return (
    <Tabs
      screenOptions={{
        tabBarStyle: { position: 'absolute', borderTopWidth: 0, backgroundColor: 'transparent' },
        tabBarBackground: () =>
          Platform.OS === 'ios' ? (
            <BlurView tint="systemChromeMaterialDark" intensity={80} style={StyleSheet.absoluteFill} />
          ) : (
            <View style={[StyleSheet.absoluteFill, { backgroundColor: 'rgba(18,18,18,0.94)' }]} />
          ),
      }}
    />
  );
}

The Android branch is a deliberate choice. A real Android blur needs the screen content wrapped in a BlurTargetView, which the tab navigator does not do for you, and a nearly opaque bar looks at home on Android anyway. Because the bar is now absolute, every screen must add bottom padding equal to the tab bar height, or the last list item hides behind it. useBottomTabBarHeight() from React Navigation gives you that number, and the tab bar guide covers the inset maths.

For headers on iOS you may not need expo-blur at all. The native stack supports headerTransparent: true with headerBlurEffect: 'systemChromeMaterial', which uses the real UIKit navigation bar blur and handles large titles correctly. Use a BlurView header only when you need the same look on Android or a custom header layout.

Two traps that make a blur look wrong

  1. Square corners on a rounded card. A borderRadius on BlurView is not enough. Add overflow: 'hidden' or the blur is drawn to the square edge of the box.
  2. The blur freezes over a list. If the BlurView is rendered before dynamic content such as a FlatList in the component tree, the blur may not update as the list scrolls. Render the BlurView after the content it sits over, which also matches how absolutely positioned overlays should be ordered anyway.

Keep blurred areas small. A full-screen blur over a scrolling list costs more on every frame, especially on Android. A blurred bar, a card, or a bottom sheet backdrop is where the effect earns its cost. For a static background, a gradient often gives a similar feel for almost nothing.

Blur, glass, or neither

On iOS 26 and later, expo-glass-effectgives you Apple’s Liquid Glass material through GlassView. It falls back to a plain View on Android and older iOS, so treat it as an iOS enhancement, with expo-blur or a solid colour as the cross-platform baseline. And if the content under the bar is mostly flat colour, a blur adds cost without any visible effect, so a translucent solid is the better choice.

A blur is impossible to judge in a static mockup because the whole point is the content moving behind it. Describe the screen, “a photo grid with a blurred floating tab bar”, and ShipNative builds it as real React Native that runs on your phone, so you can scroll under the bar and decide whether it earns its place.

Frequently Asked Questions

Why does BlurView not blur anything on Android?

By default expo-blur renders a semi-transparent view on Android instead of a real blur, because the blur method defaults to none. To get a real blur, wrap the content behind it in BlurTargetView, pass that ref to the BlurView as blurTarget, and set blurMethod to dimezisBlurView or dimezisBlurViewSdk31Plus.

Does expo-blur work in Expo Go?

Yes. expo-blur is included in Expo Go on iOS and Android, so npx expo install expo-blur is enough to start. You only need a development build if you switch to a different blur library that ships its own native code.

How do I give a BlurView rounded corners?

Set overflow: "hidden" on the BlurView as well as borderRadius. Without overflow hidden, the blur is drawn as a square and only the border radius of the invisible box changes, so the corners look sharp.

What does the intensity prop do?

Intensity runs from 1 to 100, with a default of 50, and sets how strong the blur is. On Android, blurReductionFactor (default 4) divides the intensity so the same number looks similar on both platforms. Intensity can be animated with Reanimated for blur-in effects.

Should I use expo-blur or expo-glass-effect?

expo-glass-effect gives the iOS 26 Liquid Glass material through GlassView and falls back to a plain View everywhere else, including Android and older iOS. expo-blur works on iOS, Android, and web. Use glass for iOS-first surfaces that should match the system, and blur when you need the effect everywhere.

Can an AI app builder generate blurred tab bars and headers?

Yes. Describe the look, "a photo feed with a blurred floating tab bar and a translucent header", and ShipNative generates the BlurView setup with the platform differences handled as real React Native, then runs it on your phone, which is the only honest place to judge a blur.

→

React Native Tab Bar

The surface most blurs end up on, and the inset maths that goes with it.

Read guide →
→

React Native Linear Gradient

The cheaper effect to reach for when a blur is too heavy.

Read guide →

Ship a real React Native app today

Describe, preview, and export Expo code, free to start.

Build with ShipNative
ShipNative

Build mobile apps with AI. Describe it, try it on your phone, own the code.

Features

Text to App AIApp Generator from ScreenshotPRD to Mobile App

Tools

All free toolsApp Cost CalculatorApp Name GeneratorApp Store Keyword ToolReact Native Components

Blog

All blog postsHow to Build an App Without CodingBest AI Tools for Real Mobile AppsExpo EAS App Store ChecklistLovable, Cursor & v0 for MobileBest AI App Builders in 2026React Native AI App Builder Guide
© 2026 ShipNative
PrivacyTermsFAQPricingDiscord