Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

This turned into a massive adventure and subsequently, a very large and messy post, so to spare you from having to read through the mess that I keyboard-farted out below, here's a summary:

Main goal : To find a way to selectively show the navigation bar in my app without also selectively removing the Safe area padding to prevent my content being clipped by the iPhone X notch.

Why I did it the way I did : I wanted to try and use the Navigation Bar's built-in safe area padding instead of react-native's <SafeAreaView> because the <SafeAreaView> would interfere with the built in padding and cause the headers to be unnecessarily tall.

Side effect of not doing it the standard way : There was a faint line between the header (shown in picture with height: 0 ) and content that was plainly visible when both header and content were the same color

What I tried :

  • Using <SafeAreaView>
  • Not using <SafeAreaView> and trying to header: null instead (aka "the recommended way of doing it")
  • Playing with header options to make the header disappear without causing clipped content. As a side affect (quoted from extended post below)

    i also found that header: null is functionally the same in result as headerTransparent: 'true' which I later discovered, is also functionally the same result as display: 'none' . All seem to be valid ways of making the entire header, Safe area padding and all, disappear.

  • Playing with the borderColor and borderWidth to determine if it was a border (in hindsight i should have done this more thoroughly)

  • Playing with 'opacity'
  • Shifting both the header and content around with position: 'relative', top: 6
  • Re-creating the issue in Xcode to see if it was an iOS issue (hindsight: i did this wrong)
  • This leads pretty cleanly into the answer so i'll cut it off here and continue it in my answer.

    The long, confusing, original version

    I'm using react-navigation in my react-native project (created with CRNA) and I think I have found a way to style the headers of a StackNavigator so that iOS takes care of the safe areas for you and negates the need to use <SafeAreaView> (which was interfering with the header on other screens).

    My app is arranged such that the first screen is sort of like a home screen with a grid of buttons which will eventually each have their own page in the StackNavigator . On this home screen I want to disable the header bar since there is nothing to navigate to and it just moves the content down, however, on the other screens, I want to have the header bar visible to display the back button. While using <SafeAreaView> I could only get one of the two mentioned above, either the home screen was clipped by the notch on the iPhone X, or the <SafeAreaView> moved the navigation/header bar on the other screens down and takes up space.

    However, I found that by ditching the <SafeAreaView> entirely, i was able to re-create what I wanted using header styling from react-navigation:

    App.js

    const Navigation = createStackNavigator({
        Home: HomeScreen,
        Test: PageScreen,
      headerMode: 'screen',
      navigationOptions: {
        headerStyle: { backgroundColor: colors.background},
        headerTintColor: colors.headerTint,
        headerTitleStyle: {
          fontWeight: 'bold',
    

    HomeScreen.js

     static navigationOptions = {
        headerStyle: {
            height: 0, 
            backgroundColor: colors.background //had to re-color it here too because otherwise the header would be white???
    

    This works well because it effectively removes the header from the home screen but still keeps the safe area padding that the header creates. However, there is a thin line now separating the header from the Home Screen content and i'm not sure how to make it go away. It is the only thing that gives away my header trickery and detracts from the user experience.

    Here is what I'm talking about:

    This does not affect the other screens in which i want the header visible: Apparently it actually does, the colors were just masking it...

    This line also appears on my iPhone 8 while testing the app using expo, although it is not as far down due to the smaller status bar on that device.

    I have already tried changing the headerTintColor in the navigationOptions because I thought there may be some kind of background color behind the one I set but apparently that controls the color of the text and back button. The internet also doesnt seem to have much on this from what I can immediately tell as searches for header line react-navigation come up with results about hiding the header, being unable to hide the header, and how to customize the header. Does anyone know what this line is and how I remove it? or failing that, how to make <SafeAreaView> play nice with a StackNavigator's navigation header?

    EDIT: I have also already tried the header: null, solution, however, by removing the header on the homepage of the app and not others causes a weird side effect with the <SafeAreaView> where the <SafeAreaView>'s safe area adds onto the one already built into the iOS header, causing the header to be a lot larger than it should, which is why I opted to go for height: 0 instead, since it renders the header effectively invisible, yet still keeps it's safe area.

    EDIT 2: after playing with the borderColor and borderWidth of the header, I have determined that this line is not a border...

    headerStyle: {
            height: 400,
            backgroundColor: 'green',
            borderColor: 'red',
            borderWidth: 150,
    

    EDIT 3: more findings. After playing with the CSS I have found that setting the opacity: 0 reveals a white layer behind the navigation bar... maybe this is slightly bigger than the navbar itself?

    also, it seems like header: null is functionally the same in result as headerTransparent: 'true' which I later discovered, is also functionally the same result as display: 'none'. All seem to be valid ways of making the entire header, Safe area padding and all, disappear.

    shifting it with position: 'relative', top: 6 seems to not solve the issue either

    EDIT 4: Since I have determined that this line was in fact not just appearing on the screen where i'd set the header height to 0 and instead was appearing on all screens, I think this is something that is intentionally built into iOS in order to differentiate the header from the page content.

    EDIT 4a: to confirm this theory I created a native-only xcode project and tried to recreate this by setting the nav bar and the view to black and, in contrary to my expectations, the issue did not re-create itself. So this is indeed something created by react-native and not built-into iOS i stand corrected again... How to remove navigation bar border/shadow?

    Re: edit 4. at this point im thinking just ditch the headers all together and make my own custom ones (maybe use a new navigator too) since the iOS headers seem to come witht his line built in – MoralCode Jul 5, 2018 at 7:40 holy crap all this searching and only NOW do i find this? stackoverflow.com/questions/47806909/… – MoralCode Jul 5, 2018 at 19:22 When I try it, borderBottomWidth: 0 can remove the border, but borderColor: 'red' cannot give it red color. I'm really confused. – Betty May 27, 2019 at 3:16 All the snenanagains with the border color was just me trying to figure out what was going on. Have you looked at my self-answer to seeif that solves the problem? – MoralCode May 27, 2019 at 3:58 Oh I didn't make it clear. My problem is not removing the bottom border. I want to give it another color. – Betty May 27, 2019 at 6:14

    Continued from summary at the start of the question...

    Once I realized my Xcode test was flawed i started googling for iOS only posts on StackOverflow with the same issue:

  • How to remove navigation bar border/shadow?
  • How to hide UINavigationBar 1px bottom line
  • Since these were iOS native solutions only I started looking for ways to re-create them in react. This then led me to looking for the same iOS only problem but with react keywords when I found the solution:

    How do I hide the shadow under react-navigation headers?

    While this question seems to be targeted at android, the answers also mention iOS:

    elevation: 0, // remove shadow on Android shadowOpacity: 0, // remove shadow on iOS

    Source: https://stackoverflow.com/a/42709731

    I tried this. It didnt work.

    Then further down an answer said this:

    headerStyle: { elevation: 0, shadowOpacity: 0, borderBottomWidth: 0,

    Tried it: It worked.

    TL;DR

    If you want to hide the header while using a StackNavigator in modern versions of react native without having to use a <SafeAreaView>, use the following code either in createStackNavigator({...}) or in your Screen classes' static navigationOptions = {...}:

    headerStyle: {
            backgroundColor: colors.background,
            borderBottomWidth: 0,
            height: 0,
    

    In navigation v5, in your stack screen add in your options object:

     <Stack.Screen
          name="Whatever"
          component={SomeScreen}
          options={{
            title: "Whatever",
            headerTitleStyle: { fontSize: 22, color: "#fff" },
            headerStyle: { shadowColor: "transparent" } // This is the important bit
        // whatever else you need in the screen header
    

    UPDATE V6:

    since released React Navigation V6, you can't hide header shadow using headerStyle option. instead of that you can use bolean option headerShadowVisible and set it to be false like example bellow:

    <Stack.Screen
          name="Example"
          component={ExampleComponent}
          options={{headerShadowVisible: false}}
    

    Use { elevation: 0 } as a headerStyle screen-option. I confirmed this works in React Navigation V5. I think this (or similar) may work in React Navigation V4 as well.

    <Stack.Navigator
      screenOptions={{
        headerStyle: { elevation: 0 }
      <Stack.Screen
        name="Home"
        component={HomeScreen} 
    </Stack.Navigator>
    

    As an update for v5, what worked for me was headerHideShadow: true.

    So in context:

    <LibraryStack.Navigator
      screenOptions={{
        headerHideShadow: true
    

    Update: This is only for the native-stack (i.e. 'createNativeStackNavigator'). Leaving this behind in case someone using the native-stack still lands on this question.

    More information (both for native-stack and stack): https://github.com/react-navigation/react-navigation/issues/6899

    I'm confused. Per github.com/react-navigation/react-navigation/issues/6981 there's no such prop – Hans Bouwmeester Aug 14, 2020 at 17:43 An edit to my answer: this is only for the native-stack (i.e. 'createNativeStackNavigator'). I'm leaving it instead of deleting in case someone is using the native-stack instead and still lands on this question. – pmadruga Aug 17, 2020 at 14:09 Isn’t this just covering up the line with the same color in a similar way to how it was less visible in my third screenshot? – MoralCode May 29, 2019 at 2:57

    I know this is an old question with an accepted answer, but I wanted to add a little clarity because it tripped me up. If you have nested Navigators you need to make sure you put the screenOptions on the correct one in order to see the changes.

    My set up was:

            <NavigationContainer>
                <Stack.Navigator>
                    {isLoading ? (
                        // We haven't finished checking for the token yet
                        <Stack.Screen name='Splash' component={SplashScreen} />
                    ) : userToken == null ? (
                        // No token found, user isn't signed in
                        <Stack.Screen
                            name='SignIn'
                            component={SignInScreen}
                            options={{
                                // When logging out, a pop animation feels intuitive
                                animationTypeForReplace: isSignout ? 'pop' : 'push',
                                title: 'Sign in',
                                // headerStyle: {
                                //  backgroundColor: theme.secondaryBackground,
                                // },
                                headerShown: false,
                    ) : (
                        // User is signed in
                        <Stack.Screen name='Homie' component={AuthenticatedAppNavigator} />
                </Stack.Navigator>
            </NavigationContainer>
    

    I was trying to set the options on the AuthenticatedAppNavigator component which is a nested navigator. The border was hidden once I moved the options to the parent navigator like below:

            <NavigationContainer>
                <Stack.Navigator
                    screenOptions={{
                        headerStyle: {
                            shadowOpacity: 0,
                            elevation: 0,
                    {isLoading ? (
                        // We haven't finished checking for the token yet
                        <Stack.Screen name='Splash' component={SplashScreen} />
                    ) : userToken == null ? (
                        // No token found, user isn't signed in
                        <Stack.Screen
                            name='SignIn'
                            component={SignInScreen}
                            options={{
                                // When logging out, a pop animation feels intuitive
                                animationTypeForReplace: isSignout ? 'pop' : 'push',
                                title: 'Sign in',
                                // headerStyle: {
                                //  backgroundColor: theme.secondaryBackground,
                                // },
                                headerShown: false,
                    ) : (
                        // User is signed in
                        <Stack.Screen name='Homie' component={AuthenticatedAppNavigator} />
                </Stack.Navigator>
            </NavigationContainer>
    

    Also, the elevation property only applies to Android, so shadowOpacity is needed for iOS.

    Work for me on "@react-navigation/native-stack": "^6.1.0"

    static screenOptions = { headerShadowVisible: false

    I'm a little confused...Are you trying to hide the header?

    If so simply set header to null.

    HomeScreen.js

    static navigationOptions = {
      header: null
                    thats sort of the goal, and i even tried that method, except, since the header provides its own "safe zone" buffer (because its using the native apple code) i found that the <SafeAreaView>'s additional safe area worked for the areas o the app where i'd hidden the header however in the areas where I hadn't hidden it, it would add to the already present safe area padding and so would create an excessively large header.
    – MoralCode
                    Jul 5, 2018 at 6:14
                    basically i'm trying to find a way to be selective about the header without having that affect the safe area padding. i.e. if i remove the header, I still want the safe area padding to apply, setting the header height to 0 seems to best achieve this because it remvs the header from view without also removing the safe area padding. i'll edit the question to make this more clear
    – MoralCode
                    Jul 5, 2018 at 6:16
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.