Navigation Rail

Navigation Rails provide access to primary destinations on tablet and desktop screens (md+). On mobile, use a Navbar instead. The Rail is hidden below the md breakpoint and expands to show labels between md and lg with a scrim; at lg+ the scrim disappears and the expanded state is unobtrusive.

Live demo

The demo below uses anchor="parent" so the Rail positions itself inside its container rather than the viewport.

Rail props

bind:collapsed boolean

default: true

Whether the rail is in its narrow (collapsed) state. Bind to drive it externally.

expandable boolean

default: true

Whether to show the hamburger toggle button. Set false to lock the rail collapsed.

anchor "viewport" | "parent"

default: "viewport"

viewport: fixed to the screen edge. parent: absolute within the nearest relative ancestor (good for contained demos).

railTop number

default: 0

Top offset in px — use when a top AppBar is present, e.g. railTop={64}.

fab Snippet

Optional FAB rendered above the nav items.

railFooter Snippet

Optional snippet pinned to the bottom of the rail (avatar, settings link, etc.).

rounded boolean

default: false

Adds rounded-xl corners to the rail panel.

RailItem props

href string

default: "/"

The destination URL. Active state is derived automatically from the current page URL.

label string

Text shown below the icon (collapsed) or beside it (expanded).

iconProps IconProps

Passed directly to the Icon component. Required. At minimum: { name: "symbol_name" }.

badge number

default: 0

Numeric badge on the icon. Pass -1 for a small dot with no number.

selected boolean

default: false

Force the active state regardless of current URL (useful for demo or non-route selection).

disabled boolean

default: false

Prevents navigation and dims the item.

external boolean

default: false

Opens in a new tab with rel="noopener noreferrer".

Usage

Mount the Rail at the top of your root layout alongside the page content. The Rail ghost element reserves the same width so content never slides under it.

<script>
  let collapsed = $state(true);
</script>

<!-- In your root +layout.svelte -->
<Rail bind:collapsed railTop={0}>
  {#snippet fab()}
    <FAB iconProps={{ name: 'add' }} label="New" />
  {/snippet}

  <RailItem label="Home"     href="/"        iconProps={{ name: 'house' }} />
  <RailItem label="Messages" href="/messages" iconProps={{ name: 'mail' }} badge={5} />
  <RailItem label="Settings" href="/settings" iconProps={{ name: 'settings' }} />

  {#snippet railFooter()}
    <Avatar seed="DV" />
  {/snippet}
</Rail>

<!-- Offset page content by the collapsed rail width -->
<div class="md:ml-24">
  {@render children()}
</div>

Navigation Bar

The Navbar is the mobile companion to the Rail. It renders as a fixed bottom bar and is hidden at md+. Resize to a narrow viewport to see it in action — it's already mounted on this page via the site layout.

Navbar props

ghost boolean

default: false

Renders an invisible same-height spacer after the fixed bar so page content is not obscured behind it. Always use this.

fab Snippet

Optional FAB rendered anchored above the bar at bottom-right.

NavbarItem props

href string

default: "/"

The destination URL. Active state is auto-derived from the current page.

label string

Text label shown below the icon.

iconProps IconProps

Required. At minimum: { name: "symbol_name" }.

badge number

default: 0

Numeric badge. Pass -1 for a small dot.

selected boolean

default: false

Force active state independently of URL.

Usage

Place the Navbar in the same root layout as the Rail. The two components are designed to be used together — Rail handles tablet/desktop, Navbar handles mobile.

<!-- In your root +layout.svelte, alongside Rail -->
<Navbar ghost>
  {#snippet fab()}
    <FAB size="sm" iconProps={{ name: 'add' }} label="New" />
  {/snippet}

  <NavbarItem label="Home"     href="/"        iconProps={{ name: 'house' }} />
  <NavbarItem label="Messages" href="/messages" iconProps={{ name: 'mail' }} badge={5} />
  <NavbarItem label="Profile"  href="/profile"  iconProps={{ name: 'person' }} />
</Navbar>

Breakpoint behaviour at a glance

BreakpointRailRail scrimNavbar
< md (mobile)hiddenhiddenvisible (fixed bottom)
md – lg (tablet)collapsed (96px)visible on expandhidden
lg+ (desktop)collapsed (96px)hiddenhidden