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.
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. Apple has since blessed the pattern at the system level: as explorations of iOS 26 tab bars show, Liquid Glass tab bars minimize on scroll through SwiftUI’s new tabBarMinimizeBehavior modifier, so the React Native version below now mirrors a first-party platform idiom.
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
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.
BankID Sweden Login Animation in React Native
Build the BankID Sweden login animation in React Native with Reanimated while keeping real auth in the official, certified flow. Here is the code and the rules.
Tinder swipe card animation in React Native with Reanimated
Build a Tinder-style swipe card in React Native with Reanimated and Gesture Handler. Here is the core gesture, the snap logic, and the bugs to avoid.
Voice interrupt animation in React Native: barge-in UI
Build a voice interrupt (barge-in) animation in React Native with Reanimated. Here are the four states, the audio-reactive orb, and the interrupt logic.
Wheel of fortune spinning animation in React Native (Reanimated)
Build a wheel of fortune spin in React Native with SVG and Reanimated. The key: choose the winning segment first, then animate the wheel to land on it.
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.