---
title: 'Accessibility Standards'
source: 'https://academia.sh/en/courses/frontend-quality/accessibility-standards'
course: 'Frontend Quality'
language: en
updated: '2026-08-17T18:11:05+00:00'
license: 'CC BY-SA 4.0'
---

# Accessibility Standards

The four principles that make accessibility measurable, the structure of criterion numbers, the conjunction rule for conformance levels, and conformance being defined at the scale of a process rather than a page.

Performance was tied to a measurable budget at this point: a threshold was written for
each metric, a change that crossed the threshold counted as a regression, and the
regression was caught before release. The value of this discipline was moving the
decision out of debate and into measurement — the question "is the page fast" was
replaced by "which metric crosses which threshold."

The same discipline is needed on a second quality axis. Whether an interface is usable
cannot be measured if it is left as an impression a sighted user forms by trying it with
a mouse; what cannot be measured cannot be caught when it regresses. This lesson builds
the structure that answers the question: usability is tied to criteria that are countable
and testable as true or false.

## Four Principles

Accessibility criteria are grouped under four principles. Principles are not criteria;
they cannot be tested. They are the framework that groups criteria and states which
question each one answers.

**Perceivable.** Content and interface components must be presented so a user can
perceive them. If a piece of information depends on a single sense alone, it does not
exist for a user who cannot use that sense. An image's alternative text, a video's
captions, color not being the sole carrier, and a text's contrast threshold all fall
under this principle.

**Operable.** Interface components and navigation must be usable. What this measures is
not whether the user reaches the information, but whether they can **operate** the
interface: reaching every control by keyboard, being able to exit wherever they entered,
seeing where focus is, having enough time.

**Understandable.** Information and the operation of the interface must be
understandable. Language declaration, predictable behavior, error identification, and
correction suggestions belong to this principle. A page that changes on its own when a
form field takes focus produces an interface that works but is not understood.

**Robust.** Content must be robust enough to be interpreted reliably by a wide variety of
user agents, including assistive technologies. This principle requires the markup we
produce to rely on defined contracts rather than the behavior of one particular
implementation. A component's name, role, and value being programmatically readable is
the criterion for this principle.

The order of the four principles is not arbitrary; it forms a dependency chain: something
that cannot be perceived cannot be operated, the understandability of something that
cannot be operated is never asked, and if none of them is declared robustly, none of the
three reaches assistive technology.

## What the Criterion Number Says

Every criterion has a three-part number, and the number alone locates what is being
discussed.

The first digit is the **principle**: 1 perceivable, 2 operable, 3 understandable, 4
robust. The second digit is the **guideline** under the principle; guidelines cannot be
tested either — they group criteria by topic (2.4 navigability, 3.3 input assistance, and
so on). The third digit is the **success criterion** under that guideline, and it is the
only testable unit.

So when the number 2.4.7 is read, it is known to belong to the operable principle's
navigation guideline even if the criterion's name is unknown. Numbers are never reused
once published: when a criterion is added it gets a new number, and the meaning of
existing numbers does not change. This lets two people understand the same thing from the
same number, and it is why writing the criterion number in a bug report is valuable.

The shared property of criteria is that they are **testable**: each is written so it can
be answered true or false for a given piece of content. "The page should be accessible"
is not a criterion; "the contrast ratio between the text and its background must be at
least 4.5:1" is.

## Conformance Levels

Criteria are distributed across three conformance levels: A, AA, and AAA. The level does
not describe the criterion's importance but the **cost of meeting it and the breadth of
its scope**. When level A is not met, user groups cannot use the interface at all; level
AA removes barriers that seriously hinder use; level AAA is additional requirements that
may not apply to every content type.

Levels are cumulative and evaluated by a **conjunction** rule: AA conformance means every
A criterion and every AA criterion is met. If even one A criterion fails, the surface
conforms to no level at all. The script below applies this rule to three surfaces of the
North Slope Measurement Station interface.

```js
// conformance.mjs — deriving the principle from a criterion number and computing conformance level

const PRINCIPLE = { 1: "perceivable", 2: "operable", 3: "understandable", 4: "robust" };

const CRITERION = {
  "1.1.1": ["Non-text Content", "A"],
  "1.3.1": ["Info and Relationships", "A"],
  "1.4.1": ["Use of Color", "A"],
  "1.4.3": ["Contrast (Minimum)", "AA"],
  "1.4.6": ["Contrast (Enhanced)", "AAA"],
  "1.4.11": ["Non-text Contrast", "AA"],
  "2.1.1": ["Keyboard", "A"],
  "2.1.2": ["No Keyboard Trap", "A"],
  "2.4.1": ["Bypass Blocks", "A"],
  "2.4.3": ["Focus Order", "A"],
  "2.4.7": ["Focus Visible", "AA"],
  "2.5.3": ["Label in Name", "A"],
  "3.3.1": ["Error Identification", "A"],
  "3.3.2": ["Labels or Instructions", "A"],
  "3.3.3": ["Error Suggestion", "AA"],
  "3.3.5": ["Help", "AAA"],
  "4.1.2": ["Name, Role, Value", "A"],
  "4.1.3": ["Status Messages", "AA"],
};

const LEVELS = ["A", "AA", "AAA"];

// North Slope station's three surfaces: "passed" | "failed" | "not-applicable"
const FAILED = {
  "measurement-list": ["1.4.3", "1.4.6", "4.1.3"],
  "measurement-entry": ["1.4.6", "3.3.5", "4.1.2"],
  "submission-confirmation": ["3.3.5"],
};
const NOT_APPLICABLE = {
  "measurement-list": ["3.3.1", "3.3.2", "3.3.3"],
  "measurement-entry": [],
  "submission-confirmation": ["3.3.1", "3.3.2", "3.3.3"],
};

const results = (surface) =>
  Object.fromEntries(
    Object.keys(CRITERION).map((n) => [
      n,
      FAILED[surface].includes(n) ? "failed" : NOT_APPLICABLE[surface].includes(n) ? "not-applicable" : "passed",
    ]),
  );

const levelMet = (s, level) =>
  Object.entries(CRITERION).filter(([, [, l]]) => l === level).every(([n]) => s[n] !== "failed");

function conformanceLevel(s) {
  let result = "not conformant";
  for (const l of LEVELS) {
    if (!levelMet(s, l)) break;
    result = l;
  }
  return result;
}

console.log("surface                    passed failed not-applicable   pct    conformance");
for (const surface of Object.keys(FAILED)) {
  const s = results(surface);
  const d = Object.values(s);
  const passed = d.filter((v) => v === "passed").length;
  const failed = d.filter((v) => v === "failed").length;
  const na = d.filter((v) => v === "not-applicable").length;
  console.log(
    `${surface.padEnd(26)} ${String(passed).padStart(6)} ${String(failed).padStart(6)} ${String(na).padStart(14)}  ` +
      `${((100 * passed) / (passed + failed)).toFixed(1).padStart(5)}  ${conformanceLevel(s).padStart(14)}`,
  );
}

console.log("\nremaining criteria:");
for (const surface of Object.keys(FAILED)) {
  for (const n of FAILED[surface]) {
    const [name, level] = CRITERION[n];
    console.log(`  ${surface.padEnd(26)} ${n.padEnd(7)} ${level.padEnd(4)} ${PRINCIPLE[n[0]].padEnd(16)} ${name}`);
  }
}

const PROCESS = ["measurement-list", "measurement-entry", "submission-confirmation"];
const lowest = PROCESS
  .map((y) => conformanceLevel(results(y)))
  .reduce((a, b) => (LEVELS.indexOf(a) < LEVELS.indexOf(b) ? a : b));
console.log(`\nprocess: ${PROCESS.join(" -> ")}`);
console.log(`  process conformance level: ${lowest}`);

const all = PROCESS.flatMap((y) => Object.values(results(y)));
const p = all.filter((v) => v === "passed").length;
const f = all.filter((v) => v === "failed").length;
console.log(`  criterion pass rate: ${((100 * p) / (p + f)).toFixed(1)}`);
console.log(`  criteria audited for AA: ${Object.values(CRITERION).filter(([, l]) => l !== "AAA").length}`);
```

```
surface                    passed failed not-applicable   pct    conformance
measurement-list               12      3              3   80.0               A
measurement-entry              15      3              0   83.3  not conformant
submission-confirmation        14      1              3   93.3              AA

remaining criteria:
  measurement-list           1.4.3   AA   perceivable      Contrast (Minimum)
  measurement-list           1.4.6   AAA  perceivable      Contrast (Enhanced)
  measurement-list           4.1.3   AA   robust           Status Messages
  measurement-entry          1.4.6   AAA  perceivable      Contrast (Enhanced)
  measurement-entry          3.3.5   AAA  understandable   Help
  measurement-entry          4.1.2   A    robust           Name, Role, Value
  submission-confirmation    3.3.5   AAA  understandable   Help

process: measurement-list -> measurement-entry -> submission-confirmation
  process conformance level: not conformant
  criterion pass rate: 85.4
  criteria audited for AA: 16
```

The three rows show three separate situations. The measurement list meets every A
criterion but misses two AA criteria; its level is A. The measurement entry passes
fifteen criteria, yet because it fails a single A criterion (4.1.2 Name, Role, Value) it
conforms to no level at all. The submission confirmation misses only one AAA criterion
and is at level AA.

The **not-applicable** column is not an exemption. Because the submission confirmation
page has no form, the error criteria are not evaluated on that surface; the moment a form
is added to the page, three criteria come back into scope. A not-applicable result means
the criterion has no counterpart in that content — not that a criterion with a
counterpart was skipped.

## Conformance Is a Property of the Process, Not the Page

The last part of the script shows why conformance cannot be reported surface by surface.
Submitting a measurement is a process that passes through three surfaces: the user
selects a record from the list, fills in the entry form, and sees the result on the
confirmation surface. If one link in the chain breaks, the process cannot be completed;
that is why the process's conformance level is the lowest of its links.

This rule has three extensions, and all three change a decision in practice.

**The whole page counts.** A surface's conformance is the conformance of the whole
surface, not of one part of it. A third-party component tucked in a corner of the page is
in the same scope.

**A process counts as a whole.** The listing surface alone being conformant does not mean
the measurement-submission process is conformant.

**Non-conforming content must not interfere.** Even when a section is left out of the
conformance scope, it must not block use of the rest of the page. A component that traps
focus, plays audio automatically, or locks keyboard navigation cannot be excused by being
declared out of scope.

A fourth condition concerns the choice of technology: the markup and scripts used must be
supported by assistive technologies. This condition excludes from conformance a component
declared in a way that has no defined counterpart — even if the component works in one
particular implementation.

## The Difference Between a Budget and a Criterion

The difference between a performance budget and a conformance rule shows up in the
output's last lines. 85.4 percent of criteria pass across the three surfaces; even so,
the process has no conformance level. That percentage feeds no decision.

The reason is that the two measures have different mathematical structures. Performance
metrics are defined over a distribution: a load-time metric asks that 75 percent of users
stay below a given threshold, and the remaining 25 percent are knowingly accepted.
Accessibility criteria are a conjunction: either every criterion is met or there is no
conformance. There is no averaging, because the user does not navigate an average page —
they stop at the one surface they cannot use.

This does not mean accessibility cannot be budgeted; the shape of the budget changes. In
performance the budget is a list of thresholds; in accessibility it is a **count of
zero**: the release that ships must have zero unmet A and AA criteria. Known, not-yet-fixed
defects are kept in an open list with the criterion number, the affected surface, and a
fix date. The definition of a regression is the same: if a criterion that passed
yesterday fails today, that is a regression.

## Summary

- Accessibility criteria are grouped under four principles: perceivable, operable,
  understandable, and robust. Principles are not tested; they group criteria.
- The criterion number's first digit gives the principle, the second the guideline, and
  the third the testable criterion; numbers are never reused, and they give bug reports a
  shared language.
- Conformance levels are cumulative: AA conformance means every A and AA criterion is
  met; when a single A criterion fails, the surface conforms to no level.
- Conformance is meaningful at the scale of a process, not a surface; the whole page
  counts, a process counts as a whole, and out-of-scope content must not block the rest.
- A performance budget is a distribution threshold; accessibility conformance is a
  conjunction — the criterion pass rate produces no decision, the count of unmet A and AA
  criteria does.

## Next Step

This lesson built the framework of criteria but did not open up the structure that the
criteria inspect. Criterion 4.1.2 requires a component's name, role, and value to be
programmatically readable; where does that triple live, and who produces it? The answer
is the accessibility tree introduced in the Semantic Markup and Media topic: the browser
derives a second tree from the document tree, and assistive technologies read that tree.
The next lesson takes up this derivation at the rule level, showing which element
produces which role and in what order an element's accessible name is computed.
