Z-Index & Stacking

How Tamagui automatically stacks overlays and floating content

Tamagui includes an automatic stacking system that ensures overlays like dialogs, popovers, sheets, and tooltips layer correctly without manual z-index management.

How It Works

When you open overlay components, Tamagui automatically assigns z-index values so that:

  • Later-opened content appears above earlier content - Open two dialogs? The second one stacks above the first.
  • Nested content appears above its parent - A tooltip inside a dialog automatically renders above the dialog.
  • Closing restores order - When content closes, z-index values are reclaimed.

This means you typically don’t need to think about z-index at all.

When to Set zIndex

Only set zIndex when you need to override the automatic stacking. Common cases:

  • Fixed headers/footers - If you have a sticky header at z-index: 100, overlays need to appear above it (they do by default).
  • Third-party libraries - If integrating with libraries that use high z-index values.
  • Custom stacking requirements - When you need specific layering that differs from open-order.
// Only if you need to override automatic stacking
<Dialog zIndex={200000}>
...
</Dialog>

Component Defaults

All overlay components use the automatic stacking system. Here’s where to set zIndex if needed:

ComponentWhere to set zIndex
Dialog<Dialog zIndex={...}>
AlertDialog<AlertDialog zIndex={...}>
Sheet<Sheet zIndex={...}>
Select<Select zIndex={...}>
Popover<Popover zIndex={...}>
Tooltip<Tooltip zIndex={...}>
Menu<Menu.Portal zIndex={...}>
ContextMenu<ContextMenu.Portal zIndex={...}>
ToastVia ToastViewport

Stacking Hierarchy

By default, components stack in this order (lowest to highest):

  1. Popover, Tooltip, Menu - Pure auto-stacking, starts around z-index 5001
  2. Dialog, AlertDialog, Select, Sheet - Use a higher base (100000+) to ensure they appear above most UI

Within each category, mount order determines stacking - open a popover, then another, the second is on top.

Nested Stacking

Nested floating elements automatically stack above their parent:

<Dialog>
<Dialog.Content>
{/* This tooltip will appear above the dialog */}
<Tooltip>
<Tooltip.Trigger>
<Button>Hover me</Button>
</Tooltip.Trigger>
<Tooltip.Content>
I appear above the dialog!
</Tooltip.Content>
</Tooltip>
</Dialog.Content>
</Dialog>

The system tracks parent-child relationships through React context, so nested portals always stack correctly.

Technical Details

The stacking system uses two mechanisms:

Horizontal Stacking (Siblings)

When multiple overlays open at the same level, each gets an incrementing z-index:

  • First dialog: 105001
  • Second dialog: 105002
  • Third dialog: 105003

Vertical Stacking (Nested)

When content opens inside another portal, it reads the parent’s z-index from context and adds 1:

  • Dialog opens at 105001
  • Popover inside dialog: 105002
  • Tooltip inside that popover: 105003

This ensures nested content is always visible above its parent, but sibling content opened later can still stack above.

Portal Component

The Portal component powers this stacking system. If building custom overlay components, you can use Portal’s stackZIndex prop:

import { Portal } from 'tamagui'
// Enable automatic stacking
<Portal stackZIndex>
{/* content */}
</Portal>
// Or use a high base value (like Dialog does)
<Portal stackZIndex={100000}>
{/* content */}
</Portal>

See the Portal documentation for more details.