v1.6.x-dev NDS IQ v6

Floating Action Button - National Design System

Pins to an edge of the viewport for a primary or persistent action, stacking with others on the same edge and, when it opens a panel, following that panel to its edge.

Floating Action Button

Mark any button nds-fab and give it an edge with data-fab-pos. It lifts out of the document to a fixed dock on that edge; buttons sharing an edge stack automatically, ordered by data-fab-order. No dock element to author.

Pick an edge above, then add one — it lands at the real viewport edge and opens its own panel. Turn Thumb on to watch it ride that panel out. Clear all removes them
<!-- data-fab-order stacks FABs sharing an edge: lower sits closer to it --> <button class="nds-btn nds-fab nds-primary nds-circle nds-icon-only" type="button" data-fab-pos="end" data-fab-order="0" data-panel-toggle="details" aria-label="Open panel" hidden> <i class="hgi hgi-stroke hgi-menu-01"></i> </button> <!-- Add nds-fab-thumb above and the FAB rides this panel out as it opens --> <aside id="details" class="nds-panel" data-panel-side="end" aria-label="Details" hidden>…</aside>

Grouped FAB

A FAB can be a container, not only a button. Mark an nds-btn-group and its actions travel and stack as a single dock item, at the buttons' own size and variant — add nds-vertical to run it down the edge instead of across.

The whole group is one dock item, so it stacks and travels as one. Its first button opens a panel; with Thumb on, the group rides out with it
<!-- The toggle lives on a child; with nds-fab-thumb the whole group rides --> <div class="nds-fab nds-btn-group nds-vertical" data-fab-pos="end" data-fab-order="0" hidden> <button class="nds-btn nds-subtle nds-icon-only" type="button" data-panel-toggle="share-panel" aria-label="Open panel"> <i class="hgi hgi-stroke hgi-menu-01"></i> </button> <button class="nds-btn nds-subtle nds-icon-only" type="button" aria-label="Copy link"> <i class="hgi hgi-stroke hgi-link-01"></i> </button> <button class="nds-btn nds-subtle nds-icon-only" type="button" aria-label="Email"> <i class="hgi hgi-stroke hgi-mail-01"></i> </button> </div> <aside id="share-panel" class="nds-panel" data-panel-side="end" aria-label="Details" hidden>…</aside>

Built-in Features

Auto-initialization

Every .nds-fab is routed to its edge on load. Nothing to call, no dock element to author.

Fixed Edge Docks

FABs resolve to one of the fixed edge docks — left, right, or bottom centre — so logical and physical positions never overlap.

Direction-Aware Routing

Logical start and end resolve by text direction, and a runtime direction flip re-routes them; physical left and right stay put.

Panel Following

An auto FAB lands on the edge of the panel it toggles, and an edge thumb slides aside as that panel arrives rather than being buried by it.

Automatic Stacking

FABs sharing an edge stack in a column, ordered by data-fab-order, with the lowest sitting closest to the edge.

Page-End Tuck

Near the bottom of a scrollable page each dock slides out to its edge so a fixed FAB never covers footer content.

Mixed Shapes and Sizes

Circles, edge thumbs, and multi-button groups share an edge without being resized; each keeps its own size and shape.

Programmatic Control

Register a FAB built at runtime, or by another component, straight into its edge dock through the JS API.

Usage Guidelines

Best Practices

  • Use a FAB for one primary or persistent action that should stay reachable as the user scrolls: compose, add, open filters, or start a chat
  • Keep FABs few. An edge crowded with actions loses the "primary action" meaning; move secondary actions into a Panel the FAB opens
  • Do not use a FAB for an action tied to a specific place in the content. Put an inline Button next to what it acts on instead
  • Prefer logical start and end (or auto) so the edge follows reading direction. Reserve left and right for an action that must stay on the same physical edge in any language
  • Give a FAB that opens a panel data-fab-pos="auto" so it sits on the same edge the panel slides from
  • Order a stack with data-fab-order: the lowest number sits closest to the edge. Put the primary action lowest
  • Group related actions (a share cluster, for example) in a single nds-btn-group nds-vertical so they travel and stack as one item. It is the ordinary button group — do not restyle it for the edge; pick the button variant and size you want and let the group be
  • Add nds-fab-thumb to a FAB — a button or a whole group — that should sit against the viewport edge. Do not hand-write the squared corners; the dock the FAB lands in decides them, and a hard-coded radius breaks the moment the FAB moves edge
  • Ship each FAB with the hidden attribute so it never flashes at its authored spot before routing lifts it to the edge

Modifier Classes

ClassDescription
nds-fabMarks an element (a button or a container) as a FAB. Routing moves it into its edge dock, and it gains a shadow so it reads as detached from the page. On a button it also sets the footprint — 16px larger than the same button inline (8px on small screens), so every size class still applies: LG 56, MD 48, SM 40. It also gives nds-secondary-outline and nds-subtle an opaque fill so page content cannot read through them
nds-fab-thumbTurns a FAB into an edge thumb: it gives up the dock's inset and sits against the viewport edge. The corners on that edge are squared off automatically, picked from the edge the FAB docks on — a logical start/end FAB gets the right side in both directions. The bottom dock has no side edge, so it meets the floor instead. A thumb also rides the Panel it toggles: when that panel slides from the same edge, the thumb travels aside with it instead of being buried, and returns as it closes
nds-btn-groupNot a FAB class — the Button group. Mark one nds-fab and several actions travel and stack as a single dock item, at the buttons' own size and variant. Add nds-vertical to stack it down an edge instead of across

Data Attributes

AttributeDescription
data-fab-posSet on a .nds-fab to pick its edge. Values: left, right, bottom (physical, fixed); start, end (logical, resolve by direction); auto (default, follow the toggled panel's side)
data-fab-orderSet on a .nds-fab to order the stack on its edge. Lower numbers sit closer to the edge. Default 0
data-panel-toggleSet on a FAB to open a Panel by id. With data-fab-pos="auto", the FAB follows that panel to its edge. With an explicit data-fab-pos the two are independent — the thumb only rides when both resolve to the same edge, so keep them in sync or use auto. On an nds-fab-thumb it also drives the ride: set it on the toggle inside a grouped FAB and the whole group travels
data-fab-dock-posSet on a hand-authored .nds-fab-dock to fix its edge. Docks are usually created automatically, so this is rarely needed

CSS Custom Properties

PropertyDefaultDescription
--fab-dock-offsetcalc(--nds-viewport-padding / 2)Distance from the viewport edges to the dock. Half the page gutter, so it narrows with the page on mobile
--fab-dock-gap--spacing-mdGap between stacked FABs on an edge
--fab-dock-z899Stacking order of the docks, below modals and backdrops

JavaScript API

Authored .nds-fab elements route automatically, so most pages never call this API. Use NDS.Fab.register for a FAB built at runtime or injected by another component.

// ── Register a FAB built at runtime ────────────────── // Routes by the element's own data-fab-pos (default auto) NDS.Fab.register(fabElement); // ...or force an edge, ignoring its data-fab-pos NDS.Fab.register(fabElement, 'left'); // 'left' | 'right' | 'bottom' | 'start' | 'end' // ── Resolve where a FAB would land ─────────────────── NDS.Fab.resolvePos(fabElement); // → 'left' | 'right' | 'bottom' // ── Find or create an edge dock ────────────────────── const dock = NDS.Fab.dock('right'); // the .nds-fab-dock on that edge // ── Re-scan authored FABs (e.g. after injecting HTML) ─ NDS.Fab.init();
Last Modified Date: 26/07/2026 - 12:56 AM
Was this page useful?
60% of users said Yes from 2843 Feedbacks