# Bottom app bar

> This screen's commands at the bottom edge, with an optional FAB — not its destinations.

## Anatomy

A `.bottom-app-bar` is an 80dp row of actions pinned to the bottom of the screen: the commands that belong to the screen the reader is already on, plus, optionally, that screen's [FAB](/floating-action-button.html.md).

Anatomy is the HTML. Direct `<a>` or `<button>` children holding a single icon are the actions; a `.button.extra.circle` child is the FAB and is pushed to the end. Every action is icon-only, so every one of them carries an `aria-label` — that is the only name it has.

```
<div class="bottom-app-bar">
  <button type="button" aria-label="Check">
    <span class="material-symbols" aria-hidden="true">check_box</span>
  </button>
  <button type="button" aria-label="Edit">
    <span class="material-symbols" aria-hidden="true">edit</span>
  </button>
  <button type="button" aria-label="Share">
    <span class="material-symbols" aria-hidden="true">share</span>
  </button>
  <button type="button" aria-label="More options">
    <span class="material-symbols" aria-hidden="true">more_vert</span>
  </button>
</div>
```

## Not the navigation bar

These are two different components that live in the same place, and picking the wrong one is the mistake this page exists to prevent.

|  | Bottom app bar | Navigation bar |
| --- | --- | --- |
| Holds | Commands for this screen | 3–5 destinations, the same on every screen |
| Markup | `<div class="bottom-app-bar">` | `<nav class="navigation-bar" aria-label="…">` |
| Landmark | None | `navigation` |
| Selected state | None — an action fires and is done | `aria-current="page"` on the destination |

Because a bottom app bar holds commands, it is not a `<nav>` and takes no landmark of any kind — not `<footer>` either, which is `contentinfo`. That is the same reasoning that keeps a [toolbar](/toolbars.html.md) out of the landmark list. It takes no `role="toolbar"` either: that role promises arrow-key navigation between the actions, and nothing here implements one. They are reached with Tab.

Material says never show both bars at once — pick the one that matches what the bottom of your screen is for. Nothing in the two components' styling overlaps, so a page that shows both anyway gets two correct bars stacked on top of each other rather than one broken one. See the [navigation bar](/navigation-bar.html.md) for the other half of the choice.

## With a FAB

Add the screen's FAB as the last child and it goes to the end of the bar on its own — there is no spacer element to write. Inside the bar it is flat and `secondary-container` rather than lifted and `primary-container`: the bar already carries the elevation, and a second shadow inside it reads as a sticker.

```
<div class="bottom-app-bar">
  <button type="button" aria-label="Check">
    <span class="material-symbols" aria-hidden="true">check_box</span>
  </button>
  <button type="button" aria-label="More options">
    <span class="material-symbols" aria-hidden="true">more_vert</span>
  </button>
  <button type="button" class="button extra circle" aria-label="New message">
    <span class="material-symbols" aria-hidden="true">add</span>
  </button>
</div>
```

The bar is one height whether or not a FAB is in it. Material's 72dp `with-fab` height is deprecated: 80dp, content vertically centred, both ways.

## Pinning it

The bar is an ordinary block by default, so it sits wherever you put it — which is what the demos above are doing. Add `.fixed` to pin it to the bottom edge of the viewport, clear of the device's own safe area.

```
<div class="bottom-app-bar fixed">…</div>
```

A fixed bar covers the last 80dp of the page, so leave that much padding at the bottom of the content behind it.

## Or a docked toolbar

M3 Expressive's answer to the same problem is the docked [toolbar](/toolbars.html.md) — a shorter 64dp bar holding the same kind of commands, with the emphasized action inside it rather than a FAB beside them. Both ship. This component is the app-bar-shaped version, and it stays because Material still publishes its tokens.

```
<div class="toolbar docked">…</div>
```

## Tokens

Set these on the bar itself, or in a rule of your own. They are declared on the component, so a value set on an ancestor *element* is shadowed by the bar's own default rather than inherited.

| Token | Default |
| --- | --- |
| `--md-comp-bottom-app-bar-container-color` | `var(--md-sys-color-surface-container)` |
| `--md-comp-bottom-app-bar-container-height` | `80px` |
| `--md-comp-bottom-app-bar-container-shape` | `0` |
| `--md-comp-bottom-app-bar-icon-color` | `var(--md-sys-color-on-surface-variant)` |
| `--md-comp-bottom-app-bar-icon-size` | `24px` |
| `--md-comp-bottom-app-bar-action-size` | `48px` |
| `--md-comp-bottom-app-bar-leading-space` | `4px` |
| `--md-comp-bottom-app-bar-trailing-space` | `4px` |
| `--md-comp-bottom-app-bar-fab-container-color` | `var(--md-sys-color-secondary-container)` |
| `--md-comp-bottom-app-bar-fab-trailing-space` | `16px` |
| `--md-comp-bottom-app-bar-z` | `997` |

The leading and trailing space is 4dp, not 16: an action is a 48dp target around a 24dp glyph, so it brings 12dp of its own and the glyph lands 16dp from the container edge.

The first six names are Material's own (`md.comp.bottom-app-bar.*` — the container is the whole family it publishes). `action-size`, `fab-trailing-space` and `-z` are this framework's: the actions are icon buttons and the FAB is a FAB, so Material states their values under those components instead.
