Skip to main content

Bug Fix: Bottom Tab Bar Shifted Upward — Missing Safe Area Bottom Inset

Last Updated: 15/07/2026
Type: Bug — UI Layout / Safe Area
Screen: App-wide — Bottom Tab Navigator
Severity: 🔴 High — Affects entire app, visible on all main screens

Feedback Screenshot:


1. Bug Description

The Bottom Tab Bar (navigation menu at the bottom containing: Home / Voucher / GPoint / Big Fan / Account) displays higher than its intended position — overlapping the screen content area (specifically the Event section), instead of sitting flush at the bottom of the screen beneath the iOS home indicator (black horizontal bar).

Symptoms:

  • The tab bar blocks a portion of the content at the bottom of the screen.
  • The center GPoint button floats correctly, but the rest of the tab bar sits awkwardly high and misaligned.
  • The iOS home indicator appears below the tab bar background instead of being overlaid on it.

2. Root Cause

The Bottom Tab Navigator lacks paddingBottom matching the bottom inset from the Safe Area — which represents the space reserved by the OS for the home indicator on iOS (and navigation gestures on modern Android).

On devices without a physical Home button (iPhone X or newer, and most modern Android devices), the system requires apps to manually apply bottom padding so content/UI is not obscured by navigation overlays.


3. Solution

If using React Navigation with @react-navigation/bottom-tabs:

import { useSafeAreaInsets } from 'react-native-safe-area-context';

const AppTabNavigator = () => {
const insets = useSafeAreaInsets();

return (
<Tab.Navigator
screenOptions={{
tabBarStyle: {
// Add paddingBottom matching the safe area bottom inset
paddingBottom: insets.bottom,
// Increase the overall height to maintain icon + label spacing
height: 60 + insets.bottom,
},
}}
>
{/* ... Tab.Screen configurations */}
</Tab.Navigator>
);
};

Option 2 — Wrap Tab Navigator inside a bottom-edged SafeAreaView

import { SafeAreaView } from 'react-native-safe-area-context';

const RootLayout = () => (
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}>
<AppTabNavigator />
</SafeAreaView>
);

Option 3 — Apply safeAreaInsets directly to tabBarStyle overrides

import { Platform } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

// Within the component wrapping Tab.Navigator:
const insets = useSafeAreaInsets();
const TAB_BAR_HEIGHT = 60;

<Tab.Navigator
screenOptions={{
tabBarStyle: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
height: TAB_BAR_HEIGHT + insets.bottom,
paddingBottom: insets.bottom,
paddingTop: 8,
backgroundColor: '#FFFFFF',
borderTopWidth: 1,
borderTopColor: '#F0F0F0',
elevation: 10, // Android shadow
shadowColor: '#000', // iOS shadow
shadowOffset: { width: 0, height: -2 },
shadowOpacity: 0.06,
shadowRadius: 8,
},
tabBarLabelStyle: {
fontSize: 11,
marginBottom: 2,
},
}}
/>

[!WARNING] If using position: 'absolute' for the tab bar, you must append a corresponding paddingBottom to each screen's main ScrollView / FlatList to prevent the bottom tab bar from overlapping content when fully scrolled.

<ScrollView contentContainerStyle={{ paddingBottom: TAB_BAR_HEIGHT + insets.bottom }}>
{/* content */}
</ScrollView>

4. Adjusting the Center Floating Button (GPoint Icon)

The GPoint button in the center of the tab bar floats above the rest. Ensure its offset is correctly adjusted with the insets:

// Floating center button — offset adjustment
const CenterTabButton = ({ children, onPress }) => {
const insets = useSafeAreaInsets();
return (
<TouchableOpacity
style={{
top: -20, // Floating 20px above the bar
alignItems: 'center',
justifyContent: 'center',
// Offset paddingBottom from the parent tab bar
marginBottom: insets.bottom / 2,
}}
onPress={onPress}
>
{children}
</TouchableOpacity>
);
};

5. Priority Test Devices

DeviceSafe Area CharacteristicsTest Status
iPhone 14/15 (Dynamic Island)bottom inset = 34px✅ High Priority
iPhone SE (with Home button)bottom inset = 0✅ Verify no extra gap
Android gesture navigationbottom inset = 24-48px
Android 3-button navigationbottom inset = 0

Technical Checklist

  • Locate the Tab Navigator configuration (typically in AppNavigator.tsx or BottomTabNavigator.tsx).
  • Add useSafeAreaInsets() and apply insets.bottom to both tabBarStyle.paddingBottom and tabBarStyle.height.
  • Ensure the center floating GPoint button is positioned correctly after the bottom inset changes.
  • If using absolute positioning for the tab bar, add paddingBottom = TAB_BAR_HEIGHT + insets.bottom to all ScrollViews/FlatLists in the app.
  • Test on: an iPhone with Dynamic Island, an iPhone SE, an Android device in gesture mode, and an Android device in 3-button mode.
  • Ensure react-native-safe-area-context is wrapped under a SafeAreaProvider at the app's root level.