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
Option 1 — Apply safeAreaInsets in the Tab Navigator (Recommended ✅)
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 correspondingpaddingBottomto 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
| Device | Safe Area Characteristics | Test 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 navigation | bottom inset = 24-48px | ✅ |
| Android 3-button navigation | bottom inset = 0 | ✅ |
Technical Checklist
- Locate the Tab Navigator configuration (typically in
AppNavigator.tsxorBottomTabNavigator.tsx). - Add
useSafeAreaInsets()and applyinsets.bottomto bothtabBarStyle.paddingBottomandtabBarStyle.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.bottomto 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-contextis wrapped under aSafeAreaProviderat the app's root level.