Mobile navigation is decided by thumbs and by a browser chrome that moves. Those two facts explain almost every difference between a phone layout that feels native and one that feels like a desktop site shrunk down: the reachable area is the bottom third of the screen, and the viewport height is not what 100vh says it is.
Here are the shapes, and the two CSS properties that make them work.
The bottom bar
Three to five destinations, always visible, in the reachable zone. Bottom Nav Bar by Arunachalam and Bottom menu by yadwinder are the shapes.
Rules that are not stylistic. Three to five items, because past five the targets get too small to hit; a "more" item is better than six. Icons need labels, since an icon-only bar is a memory test and the labels cost one line of type. Targets want to be at least 44 by 44 points, which is the size a fingertip actually covers. And the current destination needs a visible state that is not colour alone.
The dock
The magnifying variant, which is a desktop idea that migrated. Dock by ibelick is the most-taken one, with Dock by Anurag Mishra, macOS Dock by briidgedotone, Dock by Ruixen UI, Animated Dock by preetsuthar17 and Dock Tabs by Ali Imam as the variants.
A dock is a good desktop flourish and a questionable phone navigation, because magnification depends on hover, which touch does not have. On a phone it degrades into a bottom bar with smaller targets. Use it where the pointer exists.
The drawer
The overflow route for everything that does not fit. From the bottom on a phone, because that is where thumbs are, and it is a dialog: focus moves in, Escape closes, focus returns, and the page behind it is inert. The dialog guide has the full contract.
One decision worth making deliberately: a drawer that opens on a swipe from the edge competes with the browser's own back gesture on both platforms. Give it a visible trigger.
The two CSS properties
env(safe-area-inset-bottom). On a phone with a home indicator, the bottom 34 or so points are not yours. A bar that ignores this has its labels under the indicator and its taps intercepted. Add the inset to the bar's bottom padding, and put viewport-fit=cover in the viewport meta tag so the value is non-zero.
100dvh, not 100vh. Mobile browser chrome expands and collapses as you scroll, and 100vh refers to the largest state, so a full-height layout is taller than the visible area and the bottom is cut off. dvh tracks the current viewport, svh the smallest, lvh the largest. For anything with a fixed bottom bar, dvh is the one.
The rest of the mobile pass
A sticky header plus a bottom bar plus a banner is most of a small screen. Pick one thing to stay, per the header guide.
Hover states do not exist. Anything that only appears on hover is invisible on touch, and that includes tooltips, hover cards and reveal-on-hover actions.
:active is the feedback that replaces hover. A tap with no visual response feels broken; active:scale-95 with a transition is enough.
Test with the keyboard open. An on-screen keyboard covers the bottom third, which is exactly where the bar and the primary action live. The visualViewport API is how you know.
Where else to look
The honest list, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
| shadcn/ui | Sheet and Drawer for the overflow route | No bottom bar |
| Vaul | A bottom drawer with real gesture handling | One shape |
CSS env() and dvh | The two things that make any of this fit | Not components |
| 21st | Bottom bars, docks and mobile menus | Quality varies by author, so preview before you take it |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a mobile nav, get the previews inline, and let the agent write the file.
Frequently asked
- How many items should a bottom navigation bar have?
- Three to five. Past five the targets get too small to hit reliably, and a more item beats a sixth destination. Each target wants to be at least 44 by 44 points, icons need labels because an icon-only bar is a memory test, and the current destination needs a state that is not colour alone.
- What is safe-area-inset-bottom for?
- The home indicator area at the bottom of modern phones, which is not yours to draw in. Add the inset to the bar's bottom padding and set viewport-fit=cover in the viewport meta tag so the value is non-zero. Without it, labels sit under the indicator and taps get intercepted.
- Why is my full-height mobile layout cut off?
- Because 100vh refers to the largest viewport state, and mobile browser chrome expands and collapses as you scroll. Use 100dvh, which tracks the current viewport, especially for anything with a fixed bottom bar. svh and lvh cover the smallest and largest states when you need them explicitly.
- Is a dock good mobile navigation?
- Not really. The magnification that makes a dock feel good depends on hover, which touch does not have, so on a phone it degrades into a bottom bar with smaller targets. Use it where a pointer exists and use a plain bottom bar on phones.







