Projects included: - maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing) - manacore (Expo mobile + SvelteKit web + Astro landing) - manadeck (NestJS backend + Expo mobile + SvelteKit web) - memoro (Expo mobile + SvelteKit web + Astro landing) This commit preserves the current state before monorepo restructuring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
7.9 KiB
Header Styling Guide - Expo Router
Overview
This guide covers all available styling options for headers in Expo Router's Stack navigator.
Available Header Style Options
Basic Configuration
import { Stack } from 'expo-router';
import { useThemeColors } from '~/utils/themeUtils';
export default function Layout() {
const colors = useThemeColors();
return (
<Stack
screenOptions={{
// Header visibility
headerShown: true,
// Header title
title: 'My Screen',
// Glass effect (iOS only)
headerTransparent: true,
headerBlurEffect: 'systemMaterial',
// Colors
headerTintColor: colors.foreground,
headerStyle: {
backgroundColor: colors.background,
},
// Title styling
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 18,
fontFamily: 'System',
},
// Shadow/Border
headerShadowVisible: false,
// Back button
headerBackVisible: true,
headerBackTitle: 'Back',
headerBackTitleVisible: true,
}}>
<Stack.Screen name="index" />
</Stack>
);
}
Core Style Properties
1. headerStyle
Controls the header container's style.
headerStyle: {
backgroundColor: '#ff0000', // Background color (not needed with headerTransparent)
}
Note: Cannot set height - this is controlled by the OS.
2. headerTintColor
Sets the color for back button and title text.
headerTintColor: '#ffffff' // White text and icons
3. headerTitleStyle
Customizes the title text appearance.
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 20,
fontFamily: 'CustomFont',
color: '#000000', // Can override headerTintColor for title only
}
4. headerTitleAlign
Controls title alignment.
headerTitleAlign: 'center' | 'left' // Default: 'center' on iOS, 'left' on Android
5. headerTransparent
Makes header transparent for glass effect.
headerTransparent: true // Required for headerBlurEffect
6. headerBlurEffect (iOS only)
Adds blur/glass effect to header.
headerBlurEffect: 'systemMaterial' | 'regular' | 'prominent' |
'systemThinMaterial' | 'systemUltraThinMaterial' |
'systemChromeMaterial' | 'systemThinMaterialLight' |
'systemThinMaterialDark'
7. headerShadowVisible
Controls header shadow/border visibility.
headerShadowVisible: false // Remove shadow
Back Button Customization
headerBackVisible
Show/hide back button.
headerBackVisible: true // Show back button
headerBackTitle (iOS only)
Custom text for back button.
headerBackTitle: 'Home' // Default: Previous screen title
headerBackTitleVisible (iOS only)
Show/hide back button text.
headerBackTitleVisible: false // Only show arrow icon
headerBackImageSource
Custom back button icon.
headerBackImageSource: require('./assets/back-icon.png')
Title Customization
headerTitle
Function to render custom title component.
headerTitle: () => (
<View>
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>Custom Title</Text>
</View>
)
headerTitleAlign
headerTitleAlign: 'center' // 'center' | 'left'
Header Buttons
headerLeft
Custom left button/component.
headerLeft: () => (
<Pressable onPress={() => console.log('Left button')}>
<Icon name="menu" size={24} />
</Pressable>
)
headerRight
Custom right button/component.
headerRight: () => (
<Pressable onPress={() => console.log('Right button')}>
<Icon name="settings" size={24} />
</Pressable>
)
Search Bar (iOS 11+)
headerSearchBarOptions
Native iOS search bar in header.
headerSearchBarOptions: {
placeholder: 'Search...',
onChangeText: (text) => console.log(text),
hideWhenScrolling: true,
}
Large Title (iOS)
headerLargeTitle
Large title that collapses on scroll (iOS only).
headerLargeTitle: true
headerLargeTitleStyle
Style for large title.
headerLargeTitleStyle: {
fontWeight: 'bold',
fontSize: 34,
}
headerLargeTitleShadowVisible
Shadow for large title.
headerLargeTitleShadowVisible: false
Complete Example: Glass Header with Theme
import { Stack } from 'expo-router';
import { Platform } from 'react-native';
import { useThemeColors } from '~/utils/themeUtils';
export default function Layout() {
const colors = useThemeColors();
return (
<Stack
screenOptions={{
headerShown: true,
// Glass effect (iOS only)
...(Platform.OS === 'ios' ? {
headerTransparent: true,
headerBlurEffect: 'systemMaterial',
} : {
headerStyle: {
backgroundColor: colors.background,
},
}),
// Colors
headerTintColor: colors.foreground,
// Title styling
headerTitleStyle: {
fontWeight: '600',
fontSize: 17,
},
headerTitleAlign: 'center',
// Shadow
headerShadowVisible: false,
// Back button
headerBackTitleVisible: false,
}}>
<Stack.Screen
name="index"
options={{
title: 'Home',
headerRight: () => (
<Pressable onPress={() => console.log('Settings')}>
<Icon name="settings" size={24} color={colors.foreground} />
</Pressable>
),
}}
/>
</Stack>
);
}
Platform Differences
iOS
- Default title alignment:
center - Supports
headerBlurEffect - Supports
headerLargeTitle - Supports
headerSearchBarOptions - Back button shows previous screen title by default
Android
- Default title alignment:
left - No blur effect (use solid
backgroundColor) - No large title support
- No native search bar in header
- Back button only shows arrow icon
Common Patterns
1. Remove Header Shadow
headerShadowVisible: false
2. Custom Back Button
headerLeft: () => (
<Pressable onPress={() => router.back()}>
<Icon name="arrow-back" size={24} color={colors.foreground} />
</Pressable>
)
3. Hide Header on Specific Screen
<Stack.Screen
name="fullscreen"
options={{ headerShown: false }}
/>
4. Dynamic Title
<Stack.Screen
name="detail"
options={{
title: dynamicTitle,
// or
headerTitle: () => <CustomTitleComponent title={dynamicTitle} />
}}
/>
5. Large Title with Search (iOS)
<Stack.Screen
name="search"
options={{
headerLargeTitle: true,
headerSearchBarOptions: {
placeholder: 'Search items...',
},
}}
/>
Limitations
Cannot Customize:
- ❌ Header height (controlled by OS)
- ❌ Status bar appearance (use
expo-status-barpackage) - ❌ Exact positioning of elements (use headerLeft/headerRight instead)
Platform-Specific:
- ⚠️ Blur effects only on iOS
- ⚠️ Large titles only on iOS
- ⚠️ Native search bar only on iOS 11+
Troubleshooting
Issue: Title not visible on transparent header
Solution: Ensure headerTintColor is set to a visible color
Issue: Back button wrong color
Solution: Set headerTintColor - it controls both title and back button
Issue: Header too tall/short
Solution: Height is controlled by OS and cannot be changed. Use custom header component if needed.
Issue: Shadow visible on transparent header
Solution: Set headerShadowVisible: false