Sticky Bottom Bar
Sticky bottom bars anchor primary actions to the bottom of the viewport so they remain reachable regardless of scroll position — most commonly used for checkout-style flows and long forms.
The Sticky Bottom Bar is a persistent UI element at the bottom of the viewport. It keeps primary actions — like saving progress or submitting data — always accessible regardless of how far the user has scrolled. The pattern improves mobile usability by anchoring primary actions inside the thumb zone.
Anatomy
Section titled “Anatomy”Add a phone number to continue.
- Bottom Bar
- Status message
- Action button
When to use it
Section titled “When to use it”Use the Sticky Bottom Bar when:
- The page involves high-volume scrolling and the user needs constant access to primary actions.
- You need to display real-time global feedback or validation errors while the user interacts with fields far from the bottom of the page.
- The content exceeds 150vh (one and a half times the screen height), such as long forms.
- You want to improve mobile ergonomics by placing primary actions within the thumb zone.
Avoid the Sticky Bottom Bar when:
- The page is static and the user isn’t inputting or saving data.
- All fields and the submit button fit within a single viewport — the bar adds unnecessary visual clutter.
- The component would sit inside a modal — modals already contain their own button bar, and adding a sticky bottom bar leads to scroll-jacking and a cramped UI.
- There are no data-entry actions — the bar serves no purpose and distracts the user.
Properties
Section titled “Properties”Appearance
Three appearance states map to the form’s status: Empty form (buttons appear disabled), Error message (a concise red message appears beside the buttons on tablet/desktop, above them on mobile), and Successful form (the primary action becomes active).
Status message
Inline text used for global validation feedback. Renders inside a polite live region so screen readers announce updates without interrupting the user’s current focus.
Action button
A primary Button-Main at LG size. Secondary buttons may appear alongside the primary, but the submit verb should always read as the primary action. Disabled buttons should not receive keyboard focus — surface a clear error on click instead.
Platform considerations
Section titled “Platform considerations”Desktop
The bar spans the viewport width with the status message and button(s) arranged on a single row. Keep the bar’s elevation distinct from the page surface so it reads as a separate layer.
Tablet
Same one-row layout as desktop. Make sure the page content has bottom padding equal to the bar’s height so the last form field isn’t hidden behind it.
Mobile
The bar reflows to a one-column layout — status message above, buttons below. The thumb-zone position is the whole point of the pattern at this size.
Best practices
Section titled “Best practices”Use the bar as a workflow tool — it should help users finish, not chase them down the page.
Do
Use it for critical editing workflows where users save changes frequently, lean on it for dynamic feedback when validation messages need to be visible from anywhere on the page, place primary actions in the thumb zone on mobile, and add bottom padding to the main container equal to the bar’s height so the last field never hides beneath it. Pair it with the Stepper for multi-step forms, and use it when content exceeds 150vh.
Don't
Don’t use it for short forms that fit in one viewport, don’t nest it inside a modal that already has a fixed footer, and don’t include it on pages without data-entry actions — the bar serves no purpose and distracts the user.
Content guidelines
Section titled “Content guidelines”Submit button labels should name the action the user is about to take (“Save”, “Continue”, “Submit”) rather than generic verbs. Keep status messages concise and specific — name the field or rule that needs attention so the user can act (“Add a phone number to continue”) instead of restating that something’s wrong. When the form has multiple steps, the bar’s wording shouldn’t change between steps — predictability is the point.
Styles
Section titled “Styles”<div class="surface-default" style=" border-top: 1px solid var(--tng-color-border-contrast-default); "> <div class="p-xl fg-error-default"> <div class="tng-flex flex-wrap gap-2xl align-items-center justify-content-space-between" > <p class="flex-grow-5 | tng-text-body pb-md"> Something went awefully wrong. Please try again. </p> <button class="flex-grow-1 | tng-button">Oh well</button> </div> </div></div>Something went awefully wrong. Please try again.
Recipes
Section titled “Recipes”Sticky Bottom Bar
Section titled “Sticky Bottom Bar”The sticky bottom bar anchors a form’s primary actions to the bottom of the viewport and surfaces global validation through a live region, so it has no single WAI-ARIA interaction pattern of its own — it leans on live region behaviour for the status message and native <button> semantics for the actions, and meets WCAG 2.1 AA. Its accessibility hinges on two things: the bar sitting after the form in source order so the tab sequence runs fields-then-actions, and a polite status region that announces validation without pulling focus away from the field the user is working in.
For designers
Section titled “For designers”- The bar holds the form’s final actions, so specify it after the form in reading order — a keyboard user should tab through every field before reaching the submit action, not the reverse. Source: WCAG 2.4.3 Focus Order.
- Don’t let the bar hide the last field: reserve bottom padding on the scrolling container equal to the bar’s height so the final field is never trapped behind the sticky layer.
- When the form isn’t yet submittable, show the primary action disabled so it’s skipped in the tab order, and surface a clear, specific error on click explaining what’s missing — never leave the reason to colour or silence.
- The status message, buttons, and every state must keep accessible contrast on each supported surface. Source: WCAG 1.4.3 Contrast (Minimum).
- Validation status must never ride on colour alone — pair the error tint with text, and an icon where it helps. Source: WCAG 1.4.1 Use of Color.
- Focus styles must stay visible, meet contrast requirements on every supported surface, and be clearly distinguishable from hover. Source: WCAG 2.4.7 Focus Visible.
- Use semantic colour tokens (e.g.
foreground/error/default) rather than fixed values, so the bar adapts correctly across themes and surfaces.
For developers
Section titled “For developers”The bar is a plain surface holding a status message and one or more native <button> actions — it needs no widget role of its own. Two structural decisions carry its accessibility. First, place the bar after the form content in the DOM so the natural tab order runs fields-then-actions; the sticky positioning is purely visual and must not change source order. Second, render the status message inside a polite live region so global validation is announced as it changes without stealing focus from the field the user is in. When the form can’t be submitted, keep the primary action natively disabled so it drops out of the tab order, and reveal the reason elsewhere — the announced status message or field-level errors — rather than on a focusable-but-dead button. The per-element roles, names, and states are in the Labelling elements section below.
Labelling elements
Section titled “Labelling elements”Give every element the role, name, and state assistive technology needs.
Bar container
Presentational by default — it’s a styling surface, not a landmark, so it takes no role. Promote it to a landmark (role="region" with an aria-label, or a <section>) only when the page genuinely needs the actions discoverable as a named area; most pages don’t, and an unnecessary region just adds landmark noise.
Status message
role="status" (or aria-live="polite", which it implies) so screen readers announce validation updates at the next pause without moving focus. Its accessible name is its own text, so keep the message concise and specific (“Add a phone number to continue”). Make sure the region is in the DOM before the message lands so the change is announced rather than missed.
Action button
A native <button> primary submit — it carries its own role and keyboard operation. Its visible label is its accessible name, so name the action (“Save”, “Submit”), not a generic verb. When the action is unavailable, use the native disabled attribute so it’s removed from the tab order, rather than aria-disabled, which would keep it focusable.
Source: WCAG 4.1.2 Name, Role, Value.