Skip to content

Accessibility guidelines

olala edited this page May 6, 2026 · 18 revisions

Accessibility in Altinn Studio and Altinn apps

What it means for us

We are a team building a low-code GUI used by non-technical people to build digital public services. That gives accessibility a double meaning for us.

1. Altinn Studio itself must be accessible. The people who build services in Altinn Studio are not all developers. They include caseworkers, service designers, and subject-matter experts — some of whom rely on keyboard, screen readers, zoom, or other assistive technology. The Studio GUI has to work for them.

2. The components they pick must produce accessible end-user services. When a service owner drags a component into a form, the resulting page must be accessible to every citizen who fills it out. The builder should not have to be an accessibility expert to ship an accessible service. Our components have to make that the default outcome.

So our job is not only to build accessible UI for ourselves. It is to build a system where accessibility is the path of least resistance for everyone downstream.

How our components are built

The components in Altinn Studio and the Altinn app component library are built to meet all WCAG 2.1 AA requirements and the WAI-ARIA Authoring Practices, and to go beyond that where it improves real-world use:

  • correct semantics by default, with native HTML where possible
  • labels, help text, and error messages wired up out of the box
  • keyboard behaviour and visible focus baked in, not bolted on
  • predictable behaviour across all states (default, hover, focus, disabled, error, loading)
  • contrast and reflow tested at the design-token level so themes can't break it
  • screen-reader behaviour validated with VoiceOver and NVDA, not only axe
  • documentation that flags any prop or pattern that can introduce risk

"Beyond WCAG" means we also care about clarity, predictability, recovery from mistakes, plain language, and cognitive load — things that affect whether real users complete a service, not only whether the page passes a checker.

For Altinn this is not a compliance exercise. It is product quality, inclusion, and trust. The goal is for the platform to work for as many people as possible — both the people building services and the citizens using them.

Norwegian regulation: requirements for public and private sector

The public sector must follow 48 requirements, while the private sector must follow 35 requirements. These are minimum requirements. Filter by public or private sector to show the requirements that apply to your organisation.

Altinn is used by both. We design and build our components to meet the public-sector set (48 requirements) by default, so a service built in Altinn Studio never falls below the strictest minimum — regardless of whether the organisation using the component is public or private.

Why it matters here specifically

Decisions made in shared components scale. A weak pattern in a shared form field gets repeated across hundreds of services. A good default fixes hundreds of services at once.

That makes accessibility a core quality attribute for the design system, shared components (form fields, validation, error summaries, etc.), form and interaction patterns, and end-to-end service flows.

What "accessible" actually includes

More than screen reader support. In practice it covers:

  • semantic structure (headings, landmarks, native form elements)
  • full keyboard access
  • visible focus states
  • correct names, labels, and instructions
  • error messages tied to the right field
  • sufficient colour contrast
  • support for zoom up to 400% and content reflow
  • predictable behaviour (no surprise focus jumps, no auto-submit)
  • compatibility with screen readers, voice control, and switch devices
  • support for cognitive, visual, hearing, and motor impairments

A component passing axe or Lighthouse is not the same as a component being accessible.


For the design team

You own the patterns and defaults that the rest of Altinn will reuse. Concrete things to do:

When designing a component

  • Define keyboard behaviour explicitly: tab order, Enter, Escape, arrow keys. Don't leave it for dev to invent.
  • Specify a visible focus state for every interactive element. Don't rely on the browser default.
  • Spec the disabled, hover, focus, error, and loading states. Don't ship a component without them.
  • Don't communicate meaning with colour alone. Pair colour with icons, text, or shape.
  • Check contrast: 4.5:1 for body text, 3:1 for large text and UI components, on every state.
  • Make labels visible. Placeholder-only fields fail.
  • Plan for errors: where does the message appear, how is it linked to the field, what does the screen reader hear?

When designing a form pattern

  • Plan the error summary: where it appears, focus management, link behaviour.
  • Plan help text placement and how it associates with the field.
  • Avoid dynamic content that shifts focus or layout without a clear reason.
  • Design for mobile and 400% zoom from the start, not as a follow-up.

When reviewing a service flow

  • Walk through it keyboard-only.
  • Check whether the user can recover from a mistake on every step.
  • Check whether instructions appear where the user needs them, not buried at the top of the page.

For the dev team

You turn patterns into components that are accessible by default — so the next team that uses them gets accessibility for free.

When building a component

  • Use native HTML first: <button>, <a>, <label>, <fieldset>, <input>. Reach for ARIA only when no native element fits.
  • Connect labels to inputs (<label for> or aria-labelledby). Connect help text and errors with aria-describedby.
  • Keep focus visible. Never remove the default outline without replacing it with something equal or better.
  • Make sure tab order matches visual order. Avoid tabindex values other than 0 and -1.
  • Manage focus on dynamic UI: dialogs trap focus and restore it on close, error summaries move focus on submit, route changes announce the new page.
  • Don't rely on :hover or mousedown for behaviour. Keyboard users need it too.
  • Test with the keyboard, with VoiceOver / NVDA, and at 400% zoom. Not just axe.

When designing component APIs

  • Don't let consumers disable accessibility. For example, don't make aria-label optional on icon-only buttons.
  • Provide sensible defaults. If a prop can break accessibility, document it.
  • For composite components (date pickers, comboboxes, file uploads), follow the WAI-ARIA Authoring Practices rather than inventing your own pattern.

When writing tests

  • Add at least one keyboard-interaction test per interactive component.
  • Add automated checks (axe, Storybook a11y addon) but treat them as a floor, not a ceiling.
  • Add a screen-reader smoke check for components that change state dynamically.

Build safe defaults into shared components

A shared component should make the accessible path the easy path:

  • correct semantics by default
  • labels, help text, and errors wired up out of the box
  • visible focus baked in
  • keyboard behaviour that works without extra work
  • predictable behaviour across states
  • documentation that flags risky usage

If a component can be used in an inaccessible way, the documentation must explain the risk and how to avoid it.

Document each component

Every component should explain what it is for, list the known issues, and include short do's and don'ts so the next team picks it up correctly.

A useful component page contains:

  • What it's for — one sentence on the intended use.
  • Do — short bullets on the right way to use it.
  • Don't — short bullets on common misuse and why it breaks accessibility.
  • Known issues — open accessibility bugs or limitations, with links to the issue tracker.
  • Verify before release — what consumers must check (keyboard, screen reader, error state, zoom).