Skip to content

ExpressiveCSS

Browse documentation

Floating Action Button

A circular action that can open a menu of related shortcuts.

View as Markdown

Use one FAB for the primary action, or a FAB menu for related labelled actions. The menu opens on click and keeps ordinary Tab navigation.

See FAB menu for markup and migration guidance for removed FAB variants and speed dials.

FAB sizes

Add circle extra (or its alias circle large) to make a FAB. It is 56dp, with 16dp corners, a primary-container fill and elevation 3. Put the medium and large size classes alongside the extra. The corner grows with the container, so a bigger FAB is not a scaled-up copy of the default.

default
56dp
medium
80dp
large
96dp
<button type="button" class="circle extra" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
<button type="button" class="circle extra medium" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
<button type="button" class="circle extra large" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
Size Class Container Corner Icon
Defaultcircle extra56dp16dp24dp
Mediumcircle extra medium80dp20dp26dp
Largecircle extra large96dp28dp36dp

The large size needs the extra, because circle large on its own is the alias for the default 56dp FAB and keeps that meaning.

On an <a>, add button, because the size classes only match button or a.button.

<a class="button circle extra medium" href="/new" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</a>

For a one-off size, reset these four custom properties instead of writing new rules. Each size class sets the same four.

Token Default
--md-comp-fab-container-height56px
--md-comp-fab-container-width56px
--md-comp-fab-container-shape16px
--md-comp-fab-icon-size24px

Extended FAB

Add extend small for the extended FAB, an icon and a label in a 56dp container with 16dp corners and 8dp between the two. Wrap the label in its own <span>. The order of the two spans sets the placement, and the wrapper triggers the 16dp leading inset.

extend small
56dp
extend medium
80dp
extend large
96dp
extend small
trailing icon
<button type="button" class="extend small">
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>
<button type="button" class="extend medium">
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>

The size axis is small, medium and large, and the label role grows with the container: title-medium, title-large, headline-small. extend small is 56dp on a symmetric 16dp inset. Always specify a size, because the sizeless baseline extended FAB has been removed.

Set the container colour with a role class rather than a value. primary-container is the default, and secondary-container and tertiary-container are the other two. Each class sets the container and the label colour together, so the hover and focus state layers follow the role.

default
primary-container
secondary-container
tertiary-container
<button type="button" class="extend small secondary-container">
  <span class="material-symbols" aria-hidden="true">edit</span><span>Compose</span>
</button>
Token Default
--md-comp-extended-fab-container-height56px (80px medium, 96px large)
--md-comp-extended-fab-container-shape16px (20px medium, 28px large)
--md-comp-extended-fab-icon-size24px (28px medium, 36px large)
--md-comp-extended-fab-leading-space16px (26px medium, 28px large)
--md-comp-extended-fab-icon-label-space8px (12px medium, 16px large)
--md-comp-extended-fab-trailing-space16px (26px medium, 28px large)
--md-comp-extended-fab-container-color--md-sys-color-primary-container
--md-comp-extended-fab-label-text-color--md-sys-color-on-primary-container

FAB menu

Use fab-menu for a FAB that expands into a list of labelled actions. The trigger is an ordinary FAB. The actions are a <ul> (or <menu>) of pills, each an icon and a label at 56dp on a full corner. Click the FAB to expand the menu. Click it again, click outside, or press Esc to collapse it.

The framework manages the expanded state. The constructor sets aria-expanded on the trigger, and open() and close() update it along with the active class. Do not write either into the markup.

<div class="fab-menu">
  <button type="button" class="button extra circle" aria-label="Create">
    <span class="material-symbols" aria-hidden="true">add</span>
    <span class="material-symbols" aria-hidden="true">close</span>
  </button>
  <ul>
    <li><button type="button"><span class="material-symbols" aria-hidden="true">mode_edit</span><span>Compose</span></button></li>
    <li><button type="button"><span class="material-symbols" aria-hidden="true">image</span><span>Add photo</span></button></li>
  </ul>
</div>

When expanded, the FAB becomes the close button. It keeps the same disc on a full corner, switches from the container colour to the solid role colour, and uses a 20dp glyph. Give the trigger a second icon and it becomes the close glyph. The first icon shows while collapsed and the second while expanded, and only one is ever in the box. With one icon, the shape change is the only cue.

The menu uses the same three colour roles as the extended FAB, and one class sets both halves. The actions take primary-container (the default), secondary-container or tertiary-container. The close button takes the matching solid primary, secondary or tertiary. Material 3 pairs them this way so the close button stands out more than the actions.

<div class="fab-menu secondary-container">…</div>

FloatingActionButton manages the menu state. The menu opens upward on click. It closes on Escape, an outside click or an action's activation. When closing would hide the focused action, the component returns focus. Closed actions are inert. Tab navigation works as usual.

After six actions, the stagger ends and the remaining actions appear together. Material 3 does not recommend more than six. Actions move on the fast spatial spring and fade on the fast effects spring. So motion="expressive" gives the move a small bounce, and the fade never overshoots. Override --md-comp-fab-menu-easing and --md-comp-fab-menu-duration for the move, and --md-comp-fab-menu-effects-easing and --md-comp-fab-menu-effects-duration for the fade.

Token Default
--md-comp-fab-menu-close-button-container-height56px
--md-comp-fab-menu-close-button-container-width56px
--md-comp-fab-menu-close-button-icon-size20px
--md-comp-fab-menu-close-button-between-space8px
--md-comp-fab-menu-close-button-container-color--md-sys-color-primary
--md-comp-fab-menu-close-button-icon-color--md-sys-color-on-primary
--md-comp-fab-menu-menu-item-container-height56px
--md-comp-fab-menu-menu-item-between-space4px
--md-comp-fab-menu-menu-item-icon-size24px
--md-comp-fab-menu-menu-item-icon-label-space8px
--md-comp-fab-menu-menu-item-leading-space24px
--md-comp-fab-menu-menu-item-trailing-space24px
--md-comp-fab-menu-menu-item-container-color--md-sys-color-primary-container
--md-comp-fab-menu-menu-item-label-text-color--md-sys-color-on-primary-container

Migration

Replace .fab and .fixed-action-btn speed-dial wrappers with .fab-menu and visible labels on each action. This requires updating the markup, not just renaming the wrapper.

Remove direction, hoverEnabled, toolbarEnabled, their markup switches and speed-dial-only token overrides. Hover opening and FAB-to-toolbar expansion have been removed. Use the toolbar component for persistent commands.

Replace circle extra small with circle extra for the current 56dp FAB. Replace sizeless extend with extend small, or choose medium or large. The small extended FAB remains supported. Replace surface color classes on FABs with primary-container, secondary-container or tertiary-container and the matching on-*-container-text for icon-only FABs. General surface utilities remain available for other components.

Initialization

Expressive.AutoInit() initializes .fab-menu. To initialize it yourself, add no-autoinit. There are no component-specific options.

const instance = Expressive.FloatingActionButton.init(document.querySelector(".fab-menu.no-autoinit"));

Methods

All methods are called on the plugin instance. You can get the instance like this:
const instance = Expressive.FloatingActionButton.getInstance(elem);
.open();

Opens the FAB menu.

instance.open();
.close();

Closes the FAB menu.

instance.close();
.destroy();

Destroy the plugin instance and detach its event handlers.

instance.destroy();

Properties

Name Type Description
el Element The DOM element the plugin was initialized with.
options Object The options the instance was initialized with.
isOpen Boolean Whether the FAB menu is open.

No matching pages

  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.

    Default source: Mist Iris.

    ExpressiveCSS presets: Lagoon, Harbor, Breeze, Cobalt, Iris.

    Bold

    Soft

    Mist

    Glow