/

Mobile Navigation: Bottom Bars, Docks and Safe Areas

Thumbs and a moving viewport decide this layout. The shapes that fit, and the two CSS properties without which none of them do.

Serafim Korablev
Serafim Korablev
@korablev

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:

SourceBest forTrade-off
shadcn/uiSheet and Drawer for the overflow routeNo bottom bar
VaulA bottom drawer with real gesture handlingOne shape
CSS env() and dvhThe two things that make any of this fitNot components
21stBottom bars, docks and mobile menusQuality 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:

bash

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.

Browse mobile components →

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.

Published

Aug 20, 2026

Read time

5 min

Tags

GuideMobileReactNavigation

Share