Skip to content

Accessibility

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.

  • 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.

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.

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.