Skip to main content

Containers

Structural layout components used to group and space related content. Use to establish visual hierarchy and contain distinct page regions. Don't use as a substitute for spacing tokens.

OverviewStyleAccessibility

Description

Anatomy

PartRequired?Notes
Container root Required The outer element (div or semantic equivalent). Sets the background, border, radius, and padding via tokens.
Container header Optional A heading or labelled region at the top of the container. Anchors the section for screen readers. Use an appropriate heading level (h2-h4) based on page hierarchy.
Container body Required The main content region inside the container. Receives vertical rhythm via --op-space-* tokens applied to child elements.
Container footer Optional A bottom row for actions (e.g. Save, Cancel) or meta information (e.g. last updated timestamp). Visually separated from the body using a border or spacing.
Border Optional A 1px stroke using --op-color-border-default. Omit on containers placed on --op-color-bg-secondary surfaces where background contrast already defines the boundary.
Elevation / shadow Optional Used selectively on floating containers (drawers, popovers). Not applied to inline page containers.

Variants

States

State Behaviour
Default Static, fully visible. No interaction affordance. Content is readable and actionable.
Loading Container body is replaced by a skeleton loader or wa-spinner. Header and footer remain visible to preserve layout stability. Applied when content is fetched asynchronously (e.g. stakeholder engagement history).
Empty Container body displays an empty-state message with optional CTA. Minimum height is maintained so the page layout does not collapse. Example: 'No submissions yet — share the consultation link to get started.'
Error Container body displays an inline error message using --op-color-status-error and --op-color-status-error-bg. The header and footer remain, allowing retry or navigation actions.
Disabled Entire container and its contents are non-interactive. Opacity reduced to 0.5. Applied when a section is locked pending a prerequisite step (e.g. review stage not yet reached).

Usage guidelines

Do / Don't

Do

Apply a descriptive heading inside the container header so screen readers can announce the section.

Don't

Leave containers without a label when they contain distinct functional content — unlabelled regions are confusing for assistive technology users.

Do

Use the outlined or filled-subtle variant consistently across a page to indicate related groupings.

Don't

Mix container variants arbitrarily on the same page — inconsistent boundaries make hierarchy harder to parse.

Do

Keep container padding consistent using --op-space-16 (16px) or --op-space-24 (24px) for body regions.

Don't

Use arbitrary pixel values or mix padding scales within the same container family.

Do

For loading states, retain the container shell (header, footer) and load body content in place.

Don't

Destroy and re-render the entire container on data refresh — this causes layout shift and loses scroll position.

Layout & Spacing

Container padding (body): Default / Outlined / Filled: --op-space-16 (16px) mobile, --op-space-24 (24px) desktop Flush: 0

Container header bottom margin: --op-space-16 (16px) Container footer top margin: --op-space-16 (16px) Footer top border: 1px solid --op-color-border-default (optional, use when footer contains actions)

Gap between stacked containers: --op-space-16 (16px) default, --op-space-24 (24px) when containers are visually prominent sections

Border radius: Default / Outlined / Filled: --op-radius-md (8px) Flush: 0

Tokens

PartTokenValue
Container root background (default) --op-color-bg-primary Standard page surface. Used for default and outlined variants.
Container root background (filled-subtle) --op-color-bg-secondary Slightly recessed surface for supplementary regions.
Container root background (filled-accent / info) --op-color-status-info-bg Used for informational callout containers.
Container root background (filled-accent / warning) --op-color-status-warning-bg Used for compliance warning or caution callout containers.
Container root background (filled-accent / success) --op-color-status-success-bg Used for confirmation or completion callout containers.
Container root background (filled-accent / error) --op-color-status-error-bg Used for error state containers.
Border (outlined variant) --op-color-border-default 1px solid. Applied on all four sides. Do not use on filled variants where background contrast defines the boundary.
Header text --op-color-text-primary Heading level h2-h4 inside the container header.
Body text --op-color-text-primary Standard body copy inside the container.
Secondary / metadata text --op-color-text-secondary Timestamps, help text, supplementary labels.
Footer border --op-color-border-default 1px top border on container footer when actions are present.
Disabled overlay opacity: 0.5 No separate token — use CSS opacity on the container root.
Border radius --op-radius-md 8px. Applied uniformly.

Engineering notes

  • Containers are plain HTML elements — there is no Web Awesome (wa-*) container component. Implement using div, section, or article with Orbit utility classes or direct token application.
  • Use semantic HTML for the container root: section when the container represents a standalone document section with its own heading, article for self-contained content (e.g. a stakeholder record card), div for purely layout-structural groupings.
  • Always include an aria-labelledby attribute on section and article containers, pointing to the container's heading id. This gives screen reader users a navigable landmark.
  • Apply container styles via CSS custom properties rather than hardcoded values so that theme overrides (e.g. dark mode, high-contrast) propagate automatically.
  • For loading states, use aria-busy='true' on the container root and replace body content with a wa-spinner or skeleton. Remove aria-busy once content has loaded.
  • Do not apply role='region' explicitly unless the container has a visible label. Unlabelled regions add noise to the accessibility tree without benefit.
  • When a container is disabled, add aria-disabled='true' to the root and ensure all interactive children are also individually disabled. CSS pointer-events: none alone is not sufficient for keyboard users.
  • Avoid inline style attributes for token values in production code. Use a shared CSS class (e.g. .op-container, .op-container--outlined) that maps to tokens.

Keyboard interaction

KeyAction
Tab Moves focus to the next interactive element inside the container. Containers themselves are not focusable unless they contain interactive content.
Shift+Tab Moves focus to the previous interactive element inside or before the container.
Enter Activates a focused interactive element within the container (button, link). No action on the container root itself.

Why it matters

Government platforms serve users with diverse assistive technology needs, including screen reader users navigating complex multi-section pages such as consultation submissions or stakeholder records. Properly labelled containers create navigable landmarks that allow users to jump directly to relevant sections without reading the entire page.

Focus

Container roots are not focusable (no tabindex). Focus moves through interactive children in DOM order. When a container transitions from loading to loaded state, focus should remain on the last focused element (or move to the first interactive element inside the container if focus was on the spinner). Disabled containers must trap no focus — all children must be individually disabled or removed from the tab order.

ARIA

Role or attributeWhen to useExample
aria-labelledby Applied to section and article container roots. Points to the id of the container's heading element. <section aria-labelledby="contact-details-heading"><h2 id="contact-details-heading">Contact details</h2>...</section>
aria-busy Set to true on the container root during async content loading. Removed when loading completes. <section aria-labelledby="activity-heading" aria-busy="true"><wa-spinner label="Loading activity"></wa-spinner></section>
aria-disabled Applied to the container root when the entire section is non-interactive. Must be paired with disabling all interactive children. <section aria-labelledby="review-heading" aria-disabled="true">...</section>
role="region" Only used when the container needs to be a named landmark and a native semantic element (section, article) is not appropriate. Requires an accessible name via aria-label or aria-labelledby. <div role="region" aria-labelledby="summary-heading">...</div>

Contrast

Default container background (--op-color-bg-primary) with body text (--op-color-text-primary): meets WCAG AA (4.5:1 minimum for normal text). Filled-subtle container background (--op-color-bg-secondary) with body text (--op-color-text-primary): verify contrast ratio meets 4.5:1 — do not use --op-color-text-secondary for body content on this surface. Status-tinted backgrounds (--op-color-status-*-bg) with their corresponding text tokens: always verify at the theme level. Do not assume status tokens meet contrast requirements without checking — tinted backgrounds can fail if paired with mid-tone text. Border (--op-color-border-default) against container background: not required to meet 3:1 for non-text elements per WCAG 1.4.11, but recommended to avoid relying solely on colour to convey boundary.

Touch targets

Container roots themselves have no touch target requirement. Interactive elements inside containers (buttons, links, form controls) must meet the 44x44px minimum touch target size independently.

Things to avoid

  • Do not use colour alone to distinguish container variants — outlined vs filled variants should also differ in border presence or padding, not just background colour.
  • Do not place focusable elements inside a disabled container without also disabling them individually — keyboard users will still reach them via Tab.
  • Do not apply aria-hidden='true' to a container that has visible, meaningful content — this hides it entirely from screen readers.
  • Do not rely on visual nesting alone to imply hierarchy — use heading levels inside containers to communicate structure programmatically.

Was this page helpful?

Updated 5 October 2026