Journal

Safari-Style Scroll-to-Hide Bottom Tab Bar in React Native

This pattern is for content-immersion apps, and it has a real cost: hiding navigation reduces discoverability.

Safari-Style Scroll-to-Hide Bottom Tab Bar in React Native: a glossy App Store icon on a blue, pink and orange gradient with bubbles

TL;DR

A Safari-style scroll-to-hide bottom tab bar slides away as you scroll into content and returns when you scroll up, a content-immersion pattern that gives content the full screen. It has a real cost: hiding navigation reduces discoverability, so it belongs on reading, feed, and media screens, not navigation-heavy apps. Mechanically, track scroll direction and translate the bar's vertical offset, hidden on scroll-down, visible on scroll-up, and run it on the UI thread with a Reanimated scroll handler so it glides instead of stuttering from JavaScript state. The make-or-break details are a direction threshold to stop flicker, snapping fully rather than parking halfway, and moving the safe-area inset with the bar. Always provide a reliable way back, revealing on scroll-up, tab change, or reaching the top. A free VP0 design supplies the bar and its hidden and shown states.

What is a scroll-to-hide bottom tab bar?

A tab bar that slides away as you scroll down into content and slides back when you scroll up. Safari does it, Instagram does it: the bottom navigation disappears to give the content the full screen, then reappears the moment you signal you want to navigate by scrolling up. It is a content-immersion pattern, the chrome gets out of the way when you are reading and comes back when you are done. In React Native the effect is a tab bar that translates off the bottom edge based on scroll direction, and done well it feels effortless.

The honest framing first: this pattern is for content-immersion apps, and it has a real cost. Hiding navigation maximizes content but reduces discoverability, a user cannot tap a tab they cannot see. So it is the right call for reading-heavy, feed-heavy, or media screens, and the wrong call for a navigation-heavy app where users hop between tabs constantly. The pattern is great; using it on the wrong app frustrates people who keep scrolling up just to find the nav.

How does it actually work?

Track scroll direction on the UI thread and translate the bar accordingly. The mechanism is: read the scroll position as it changes, compare it to the last position to get a direction, and animate the tab bar’s vertical offset, down (hidden) when scrolling down, up (visible) when scrolling up. The key to it feeling smooth is running this off the JavaScript thread. A Reanimated scroll handler, from a library pulling over 5,266,534 weekly npm downloads, reads scroll and drives the translation on the UI thread, so the bar tracks your finger instead of lagging behind it.

This is the same off-the-main-thread discipline that makes a Reanimated bottom sheet feel native: if the animation is driven from JavaScript state on every scroll event, it stutters; driven on the UI thread, it glides. The scroll handler is where the smoothness lives.

What are the details that make or break it?

Thresholds, snapping, and the safe area. Three details separate a polished auto-hiding bar from an annoying one:

  • A direction threshold. Do not hide on a one-pixel jitter; require a few pixels of consistent scroll before toggling, or the bar flickers as the user’s finger wobbles.
  • Snap fully, never halfway. The bar should be either shown or hidden, animating cleanly between the two, not parked at a partial offset that looks broken.
  • Move the safe-area inset with it. The bottom safe-area padding belongs to the bar, so when it hides, the content should reclaim that space, and when it shows, the content must not sit under it.

Get the threshold wrong and it flickers; get the safe area wrong and content hides behind the bar or leaves an empty gap. These are the details that make a custom bottom tab bar feel native rather than homemade.

When should the bar always come back?

On the moments that signal intent to navigate. A good auto-hiding bar is not purely scroll-driven; it reveals itself on the actions where the user clearly wants the nav: reaching the top of the list, switching tabs, or after a pause in scrolling. Hiding the bar is fine; trapping it hidden is not, so there must always be an obvious, low-effort way to get it back. Reliably, scrolling up even a little should bring it straight back, so the nav is never more than a small gesture away.

The screens, the tab bar, its hidden and shown states, the content layout that reclaims the space, come as free VP0 designs built on the standard iOS tab-bar conventions, so an agent wires the scroll handler onto a bar that already handles safe area and snapping rather than improvising the offsets. The animation is a well-known recipe; the judgment is knowing this belongs on a content screen and giving users a reliable way back to the nav.

Key takeaways: a scroll-to-hide bottom tab bar

  • It is a content-immersion pattern: the bar hides on scroll-down to give content the full screen and returns on scroll-up.
  • Use it on the right apps: reading, feed, and media screens, not navigation-heavy apps where hidden tabs hurt discoverability.
  • Drive it on the UI thread: a Reanimated scroll handler tracks direction and translates the bar smoothly, instead of stuttering from JavaScript state.
  • Mind the details: a direction threshold to stop flicker, full snapping not halfway, and a safe-area inset that moves with the bar.
  • Always provide a way back: reveal on scroll-up, tab change, or reaching the top, so the nav is never trapped off-screen.

Frequently asked questions

How do I make a bottom tab bar hide on scroll in React Native? Track the scroll position as it changes, derive a direction by comparing it to the last position, and animate the tab bar’s vertical offset, hidden when scrolling down, visible when scrolling up. Run this with a Reanimated scroll handler on the UI thread so the bar tracks the scroll smoothly, add a small direction threshold to prevent flicker, snap fully between shown and hidden, and move the safe-area inset with the bar. A free VP0 design supplies the bar and its states.

Why does my auto-hiding tab bar stutter? Almost always because the animation is driven from JavaScript state on every scroll event, which floods the JS thread. The fix is to read scroll and drive the translation on the UI thread with a Reanimated scroll handler, so the bar moves in sync with the finger rather than lagging behind it. The same off-the-main-thread approach is what makes other gesture-driven animations feel native.

When should I use a scroll-to-hide tab bar? On content-immersion screens, reading, feeds, and media, where giving content the full screen improves the experience and users are not constantly switching tabs. Avoid it on navigation-heavy apps, because hiding the tabs reduces discoverability and frustrates users who hop between sections. The pattern is great in the right place and annoying in the wrong one, so match it to how navigation-heavy your app really is.

How do I stop the tab bar from flickering? Add a direction threshold so the bar only toggles after a few pixels of consistent scroll, rather than reacting to a one-pixel jitter as the user’s finger wobbles. Also snap the bar fully to shown or hidden instead of leaving it at a partial offset. Together these prevent the rapid flicker that happens when tiny scroll changes repeatedly flip the bar’s state.

Does hiding the tab bar hurt usability? It can, if there is no reliable way to get it back. Hiding navigation maximizes content but a user cannot tap a tab they cannot see, so the bar must reappear on clear intent signals: scrolling up, switching tabs, or reaching the top. Ideally, even a small upward scroll brings it straight back, so the nav is never trapped off-screen and the immersion never becomes a dead end.

What the VP0 community is asking

How do I make a bottom tab bar hide on scroll in React Native?

Track the scroll position as it changes, derive a direction by comparing it to the last position, and animate the tab bar's vertical offset, hidden when scrolling down, visible when scrolling up. Run this with a Reanimated scroll handler on the UI thread so the bar tracks the scroll smoothly, add a small direction threshold to prevent flicker, snap fully between shown and hidden, and move the safe-area inset with the bar. A free VP0 design supplies the bar and its states.

Why does my auto-hiding tab bar stutter?

Almost always because the animation is driven from JavaScript state on every scroll event, which floods the JS thread. The fix is to read scroll and drive the translation on the UI thread with a Reanimated scroll handler, so the bar moves in sync with the finger rather than lagging behind it. The same off-the-main-thread approach is what makes other gesture-driven animations feel native.

When should I use a scroll-to-hide tab bar?

On content-immersion screens, reading, feeds, and media, where giving content the full screen improves the experience and users are not constantly switching tabs. Avoid it on navigation-heavy apps, because hiding the tabs reduces discoverability and frustrates users who hop between sections. The pattern is great in the right place and annoying in the wrong one, so match it to how navigation-heavy your app really is.

How do I stop the tab bar from flickering?

Add a direction threshold so the bar only toggles after a few pixels of consistent scroll, rather than reacting to a one-pixel jitter as the user's finger wobbles. Also snap the bar fully to shown or hidden instead of leaving it at a partial offset. Together these prevent the rapid flicker that happens when tiny scroll changes repeatedly flip the bar's state.

Does hiding the tab bar hurt usability?

It can, if there is no reliable way to get it back. Hiding navigation maximizes content but a user cannot tap a tab they cannot see, so the bar must reappear on clear intent signals: scrolling up, switching tabs, or reaching the top. Ideally, even a small upward scroll brings it straight back, so the nav is never trapped off-screen and the immersion never becomes a dead end.

Part of the React Native & Expo: Mobile Frontend Architecture hub. Browse all VP0 topics →

Keep reading

Custom Bottom Tab Bar in React Native: The AI Prompt: the App Store logo as a frosted glass icon on a pink and blue gradient with bubbles
Guides 5 min read

Custom Bottom Tab Bar in React Native: The AI Prompt

Generate a custom bottom tab bar: when custom beats stock, the tabBar-prop seam, the prompt contract, and the accessibility floor custom must re-earn.

Lawrence Arya · June 5, 2026
Hero Animations in React Native: Shared Elements in 2026: a glowing iPhone home-screen icon on a purple and blue gradient
Guides 5 min read

Hero Animations in React Native: Shared Elements in 2026

Reanimated tags first, the manual overlay in your pocket: how shared element transitions actually work, and where the bridge breaks.

Lawrence Arya · June 7, 2026
Live-Stream Tip Shower Animation in React Native: a glowing iPhone home-screen icon on a purple and blue gradient
Guides 6 min read

Live-Stream Tip Shower Animation in React Native

The gift rain is a business mechanic, not decoration: UI-thread particles, value encoded in spectacle, and a shower that only plays once the payment confirms.

Lawrence Arya · June 7, 2026
React Native Game Loop Engine Hook: a vivid neon 3D App Store icon on an orange, pink and blue gradient
Guides 5 min read

React Native Game Loop Engine Hook

React's event model fights a per-frame tick: run a frame-synced loop off the JS thread with Reanimated, pass delta time, and add start/stop/pause.

Lawrence Arya · June 7, 2026
Customer Support Chat UI (Crisp) in React Native: Honest: a glass iPhone UI wireframe icon on a holographic purple gradient
Guides 5 min read

Customer Support Chat UI (Crisp) in React Native: Honest

Build in-app support chat: native UI over the vendor API, honest reply-time expectations, bot disclosure, offline capture, and deflection that respects users.

Lawrence Arya · June 5, 2026
Expo OTA Update Force Refresh UI: Restart Etiquette: a glossy App Store icon on a blue, pink and orange gradient with bubbles
Guides 5 min read

Expo OTA Update Force Refresh UI: Restart Etiquette

Design the OTA update experience: silent-by-default apply, restart prompts that respect tasks, the forced path for breaking changes, and honest limits.

Lawrence Arya · June 5, 2026