ESC

Type to search the knowledge base.

WCAG Principles: POUR

Perceivable, Operable, Understandable, Robust — the four WCAG principles with concrete frontend examples, levels, and how to use them in reviews.

beginner5 min read
  • accessibility
  • wcag
  • pour
  • a11y

WCAG (Web Content Accessibility Guidelines) organizes requirements under four principles: Perceivable, Operable, Understandable, Robust — POUR. If you can classify a bug under POUR, you can explain why it matters to users and map it to success criteria instead of hand-waving “a11y.”

Docs: WCAG 2 overview (W3C), WCAG 2.2, How to meet WCAG, MDN Accessibility.

Conformance levels (A, AA, AAA)

Level Meaning in practice
A Minimum baseline — without these, many users are blocked
AA Common legal/product target (e.g. many public-sector and enterprise policies)
AAA Highest; excellent where feasible, not always required for every criterion on every page

Most product teams aim for WCAG 2.x Level AA. POUR is stable across 2.0/2.1/2.2; versions add criteria under the same principles.

P — Perceivable

Information and UI must be presentable in ways users can perceive — not only via a single sense or medium.

Frontend examples:

Do Don’t
Text alternatives for images that convey meaning Icon-only status with no name
Captions/transcripts for multimedia Video announcements with no text path
Sufficient color contrast for text/UI Light gray body text on white
Don’t rely on color alone for errors Red outline only, no text/icon
Resize text / reflow without loss Fixed pixels that clip at 200% zoom
<img src="/chart.png" alt="Revenue up 12% quarter over quarter" />
<!-- Decorative -->
<img src="/swirl.svg" alt="" />
/* Prefer system-aware motion for vestibular safety (also Operable) */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Related: color contrast, do not rely on color alone, images alt.

O — Operable

Users must be able to operate the interface — keyboard, pointer, time limits, seizures/vestibular safety, navigation aids.

Frontend examples:

Do Don’t
All functionality via keyboard Mouse-only drag with no alternative
Visible focus outline: none with no replacement
Skip links to main content 200 tab stops through mega-nav
Sensible focus order matching visual order tabindex chaos / CSS order for reading order
Controllable time limits Session expired with no warning/extension
No seizure-inducing flashes Unchecked large flashing ads
<a class="skip-link" href="#main">Skip to main content</a>
<!-- … nav … -->
<main id="main">…</main>
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

Controls that navigate should be links; actions should be buttons — links vs buttons. Modals need focus management — dialog, focus management.

Touch target size and spacing matter for motor disabilities and real phones — see touch-target guidance on this site.

U — Understandable

Information and operation must be understandable — readable language, predictable UI, input assistance.

Frontend examples:

Do Don’t
Page lang attribute Missing or wrong lang
Clear labels on inputs Placeholder-only fields
Consistent nav across pages Random link reordering per route
Error identification in text “Invalid” with no field reference
Help for complex inputs Cryptic validation only after full form wipe
<html lang="en">
…
<label for="card">Card number</label>
<input
  id="card"
  name="card"
  inputmode="numeric"
  autocomplete="cc-number"
  aria-describedby="card-hint card-err"
/>
<p id="card-hint">16 digits, no spaces required.</p>

Forms are where Understandable fails loudest — forms, labels, and inputs, accessible forms and errors.

Predictable behavior also means components that don’t trap focus unexpectedly and don’t change context on focus alone (classic WCAG gotcha with aggressive onfocus navigation).

R — Robust

Content must be robust enough to be interpreted by a wide range of user agents, including assistive technologies — valid-ish semantics, correct names/roles/states, future-friendly markup.

Frontend examples:

Do Don’t
Prefer native HTML controls <div role="button"> without keyboard
Accurate ARIA when native isn’t enough ARIA that lies (aria-expanded never updated)
Unique IDs for label associations Duplicate IDs breaking labels
Stable accessible names Names that change without reason mid-task
Test with AT / accessibility tree Pixel-only QA
<!-- Robust: native -->
<button type="button" aria-expanded="false" aria-controls="panel">
  Filters
</button>

ARIA is a compatibility layer, not a styling API. First rule of ARIA: don’t use ARIA if a native element works. See ARIA roles overview, accessible names.

Using POUR in code review

Instead of “please fix a11y,” write:

Operable: Modal traps focus incorrectly — Tab escapes to background (WCAG 2.x focus order / modal pattern). Use <dialog showModal()> or return focus on close.

Perceivable: Error state is color-only; add text / aria-invalid + message.

Understandable: Submit errors are toast-only; associate with fields via aria-describedby.

Robust: Custom listbox missing aria-activedescendant updates; follow APG.

Mapping to POUR keeps reviews teachable and maps to audit tools and legal language.

Automated checks vs POUR judgment

Axes/Lighthouse catch many Robust/Perceivable issues (contrast, names, invalid ARIA). They miss:

  • Logical focus order in complex widgets
  • Whether a flow is completable with AT
  • Clear error wording
  • Motion sickness from custom animations

Use automation as a gate, not a certificate. Manual keyboard + one screen reader pass on critical flows is still required.

POUR and performance / security (adjacent)

  • Slow interactions (INP, Core Web Vitals) hurt Operable for everyone, especially motor/cognitive load.
  • XSS that injects UI can break names/roles or phishing overlays — Robust/Understandable fail in the wild.
  • Layout shift (CLS) can move targets mid-click — Operable/Perceivable pain.

Interview angle

Spell POUR and give one concrete UI failure per letter. Mention AA as the common bar. Prefer native HTML under Robust. Differentiate automated vs manual testing.

One-liner:

“POUR: can users sense it, use it, understand it, and can AT reliably parse it?”

Further reading

Related guides