Part 5. The method profiles
AFDS user guide
The method profiles: choosing a way of building, or not
Everything you have read so far applies to every AFDS package; this section does not.
Part III of the specification describes four ways of building interfaces, each packaged as a method profile: a named group of requirements that a package may claim, and against which it can then be measured. A package that claims none of them still conforms. Clause 4.3 puts it without hedging: an organisation whose brand palette and layout conventions are already fixed "can satisfy the core completely", gets the contract, the evidence, the uncertainty records and the portability, and does not get the layout method — and "That is the intended outcome, not a loophole." The material below is the most opinionated writing in the specification, and it is also the most optional.
An earlier edition of this guide presented the layout method as the project method and described five of its rules as "non-negotiable". That was wrong structurally rather than in detail: it left a reader with a fixed breakpoint system believing they had already failed, when in fact they had declined a profile, which is a permitted act requiring no explanation.
What a method profile is
A method profile is a named, versioned set of requirements about how components are built, which a package may claim and against which it can then be measured (clause 20.1).
A profile is not a level, and this is the point most often misread: the four profiles are not ordered, do not build on one another, and carry no ranking (clause 20.1). A package claiming three profiles is not more conformant than a package claiming one, and a package claiming none is not deficient. There is no "highest" profile to aim at, because the profiles are about different subjects, not different degrees of the same subject.
Three rules keep a profile from drifting into the core, and between them they tell you exactly which of your obligations survive if you drop a profile claim (clause 20.1).
A profile does not restate a core requirement: where a profile appears to require something Part II already requires, Part II governs and the profile's restatement has no independent force, so removing a profile claim takes nothing away that Part II required of you.
A profile does not weaken a core requirement, and the specification is blunt about the consequence: a profile that purported to excuse a package from a Part II obligation "would not be a profile, and a package claiming it does not conform".
A profile imposes at least one requirement that the core does not, because without that rule a profile could restate nothing, weaken nothing and require nothing, which would make it a label rather than a commitment — "the kind of unearned claim this specification exists to prevent". Where the intended content of a profile turns out to be entirely a matter of citing existing work, the specification says the right action is to cite that work directly and define no profile.
Three readers, three consequences.
For a designer, a profile is a set of design decisions somebody has already argued out; you can take the argument or make your own.
For a developer, it is a set of build-time constraints you either accept for the whole package or do not claim.
For a tester, it tells you which extra checks are in scope — and, equally usefully, which are not: a test report that fails a package against afds-layout-intrinsic when the manifest does not claim it is a defective report, because clause 4.3 states that a package "MUST NOT be judged against a method profile it does not claim" and that a consumer "MUST NOT treat the absence of a method-profile claim as a defect".
Declaring which profiles a package claims
A package that claims one or more method profiles declares them in a methodProfiles array in its manifest, and each element has to be a profile identifier defined in Part III or a local identifier permitted by clause 20.4 (clause 20.2).
A package claiming no profile either omits the array or supplies it empty, and the two forms have identical meaning (clause 20.2). There is no third state, and an omitted array is not an unanswered question.
{
"methodProfiles": []
}
{
"methodProfiles": [
"afds-patterns-native-first"
]
}
Both are conforming declarations: the first says the package adopts none of Part III's method choices, and the second says it adopts one of them, whole, and none of the other three.
Method and completeness are different questions
The manifest carries a second, unrelated field: conformanceProfile states how much of the package hierarchy is present, using afds-tokens, afds-components or afds-full (clause 34).
It says nothing whatever about method, and methodProfiles says nothing whatever about completeness.
The specification requires that the two axes be declared separately and forbids conflating them (clauses 20.2, 4.5). A package can be complete and claim no method profile; a package can claim every method profile in Part III and contain tokens only. Software reading a package "MUST NOT infer a value of either field from the other" (clause 20.2), and clause 4.5 repeats the prohibition for consumers generally. The reason is that the two fields answer different questions: "is there enough here for me to use?" is a completeness question, and "was this built the way my system is built?" is a method question.
Do not use the bare word "conformance" for either axis: say "completeness profile" or "method profile", and say which.
Section B covers conformanceProfile and the completeness axis; this section covers method only.
A profile is claimed whole
A package does not claim a profile in part, and a package that satisfies some but not all of a profile's requirements does not list that profile in methodProfiles (clause 20.3).
The reasoning is practical: a partial claim cannot be interpreted, because if a package could claim the layout profile while using layout media queries, the claim would tell a reader nothing, and every consumer would have to re-derive from the component contracts the very thing the claim was supposed to summarise.
That leaves the question every real team hits: what do you do when you like nine tenths of a profile?
Adopting a profile's requirements without claiming the profile is permitted, and the specification says it is "expected to be common".
You may satisfy any requirement in Part III, cite the clause it came from, and record it with the requirement kind that honestly describes its status under clause 13 — most often project-convention — but you may not describe that as claiming the profile, in the manifest or in any human-readable artefact (clause 20.3).
If you adopt most of a profile and depart from it deliberately, clause 20.3 describes a well-defined position: you do not list the profile, you record the departure as a requirement of kind product-deviation, you name the clause you depart from, and you state why — with clause 13 requiring a product-deviation to record its cost as well as its reason.
The specification judges that more informative than a partial claim would have been, because it identifies the specific difference instead of leaving a reader to hunt for it.
The four profiles Part III defines
Identifier, as it appears in methodProfiles | What claiming it commits the package to | Clause |
|---|---|---|
afds-layout-intrinsic | Intrinsic, available-space layout built from composable primitives: five axioms in every component, twelve single-purpose primitives, no layout media queries, no Shadow DOM in primitives, forced-colours surface delineation inspected and evidenced | 21 |
afds-reflow-scoped | The WCAG 1.4.10 two-dimensional exception claimed only on semantic grounds, scoped to its own scrollable container, never reaching the page, with four records per claim and four environment values per reflow assertion | 22 |
afds-typography-colour | One modular scale for type and space anchored at 1rem, a 60ch measure, colour that never carries meaning alone, a default target level of Level AA, and contrast recorded per token pair | 23 |
afds-patterns-native-first | Native HTML first, published patterns adopted by reference for genuine composites, a package-level pattern registry, and a gated catalogue of eight priorities | 24 |
An identifier defined in Part III is not used for any other set of requirements, and the identifiers are stable for the life of this major version (clause 20.4).
You may also define your own profile, and an identifier for a profile not defined in the specification has to be namespaced with a prefix that is not afds-, so that no reader mistakes a local profile for one defined by the project (clause 20.4).
A locally defined profile also has to satisfy clause 20.1, clause 20.3 and clause 20.5, and a package claiming a local profile that does not satisfy those clauses does not conform (clause 20.4).
Saying where a profile's ideas came from
Every profile states its provenance, and the statement identifies four things (clause 20.5):
- what the profile adopts from work outside the project, described specifically enough that a reader can tell which parts are borrowed;
- the source of each adopted idea, identified well enough to be found, which for a published work means author and title;
- what the profile changes about an adopted idea, including anywhere it is stricter than its source or reaches a different conclusion;
- what originates in the profile itself and has no external source.
The fourth element carries the weight. Clause 20.5 calls it the one most likely to be omitted and the most important to include, because a profile that lists its influences and stays quiet about its own inventions "launders an untested opinion as settled practice"; stating that a rule originates here and rests on nobody else's reasoning is not a weakness, because it tells a reader exactly which rules to argue with.
Two prohibitions follow, both from clause 20.5. A provenance statement does not attribute a requirement to an external source that does not support it, and a package whose profile does so does not conform; and a provenance statement is not replaced by a bibliography, because a list of references establishes that a document was read, not which idea came from where.
If you claim one of the four profiles defined in Part III, you inherit its provenance statement and are not required to restate it (clause 20.5); if you define a local profile, you supply your own, as a structured object rather than only as prose (clause 20.6).
| Member | Type | Required | Content |
|---|---|---|---|
adopted | array | Yes, may be empty | What the profile takes from work outside the package |
changed | array | Yes, may be empty | What the profile alters about an adopted idea |
originates | array | Yes, and it may not be empty | What the profile asserts on its own authority |
statement | string | No | Prose accompanying the structured members |
Each adopted entry records what is adopted and its source as an object with author, title, and uri where one exists; each changed entry records what changed, references the adopted entry it changes, and records whether the change is stricter, weaker or different; each originates entry records what originates in the profile and references the clause it applies to (clause 20.6).
A weaker value is permitted and is not a conformance failure — a profile may legitimately relax something its source requires, and recording that plainly is the point of the member; recording such a change as stricter, or omitting it, is what is not permitted.
originates may not be empty, and clause 20.6 explains why a validator can treat an empty one as a defect without reading a word of the content: a profile with nothing in originates claims to adopt everything and add nothing, and clause 20.1 requires it to add at least one thing.
For tool authors there is a limit alongside that: a validator can check that every changed entry references a real adopted entry and that originates is non-empty, but it cannot determine whether an attribution is truthful, and clause 20.6 states it "MUST NOT be represented as doing so".
The intrinsic layout profile — afds-layout-intrinsic
Start with the problem the profile is answering, because it is not the problem breakpoints were invented for. A user at 400% zoom, a user who has raised their default font size, and a component nested inside a narrow sidebar can all present a component with far less room than the viewport suggests, and no set of breakpoints anticipates the combinations (clause 21.5). Designing for the web means designing without seeing the final combination, so the profile asks for programs that respond to space rather than artefacts tuned to named widths. Claiming this profile means every component in the package meets what follows; not claiming it means none of what follows applies to your package, and no reviewer may hold you to it.
The profile's own statement is three sentences (clause 21.1):
Layout responds to the space actually available to it, not to the width of the viewport. Every dimension is expressed so that it moves with the user's settings. Interfaces are composed from single-purpose primitives rather than assembled from bespoke per-screen layouts.
The five axioms
Clause 21.2 opens with the scope: a package claiming this profile "MUST satisfy the following five axioms in every component it contains". These are the specification's own words:
- The measure MUST NOT exceed 60ch, subject to the exception mechanism in clause 23.3.
- Every dimension MUST be user-relative. Author-fixed dimensions MUST NOT be used, except for hairline borders.
- Layout MUST respond to available space rather than viewport width.
- An element MUST NOT be given a fixed height.
- Layout MUST be complete with JavaScript disabled.
Note the qualifier on axiom 1: the 60ch measure is subject to the documented per-container exception mechanism of clause 23.3, which belongs to a different profile (afds-typography-colour) and is described in D.7 below.
The axioms are stated as absolutes because each one fails in the presence of a single exception (clause 21.2) — one fixed height in a shared primitive reintroduces clipping under text-spacing overrides across every screen that uses the primitive, and the primitive's other correctness does not compensate.
What the "no px" rule actually prohibits
Axiom 2 gets heard as a superstition about pixels, so the clause states it precisely: it prohibits values frozen against the user's font-size and zoom settings. It does not assert that the CSS pixel is a badly designed unit — a CSS pixel is an angular reference measurement, and the objection is to author-chosen values that cannot move, not to the unit (clause 21.2).
The obvious escape hatch is closed specifically: a package claiming this profile "MUST NOT justify author-fixed dimensions on the grounds that the value is small" (clause 21.2), so a 2px gap is as frozen as a 200px one, and the single documented exception is hairline borders, named in axiom 2 itself.
One caution on units: the specification enumerates no list of permitted units, requiring only that dimensions be user-relative (clause 21.2) and that the measure be expressed in ch or another font-relative unit (clause 23.3).
rem, em, ch, cap and percentages all satisfy that in practice, but treat that as guide guidance rather than a closed list, because the clause does not give one.
JavaScript is not prohibited
Axiom 5 is a layout requirement and not a general prohibition on JavaScript, and clause 21.2 says so explicitly. A component may require JavaScript for its interaction; its layout may not require JavaScript to be correct, "because a layout that collapses before script executes is a layout that fails intermittently on slow connections and permanently when script errors" (clause 21.2), so a developer reading axiom 5 as "no interactive components" has read it too widely.
The twelve primitives
A package claiming this profile builds layout from single-purpose primitives, each of which does one thing, and the profile adopts twelve (clause 21.3). Each one, if present in the package, has a component specification conforming to Part II, and declares the semantics it does not supply (clause 21.3).
| Primitive | What it arranges | Supplies no | Clause |
|---|---|---|---|
| Stack | Vertical rhythm between adjacent siblings | List semantics, grouping, heading structure | 21.3 |
| Box | Intrinsic surface: padding, border treatment, colour inheritance | Semantic role | 21.3 |
| Center | Constrains the measure, with gutters growing outward | Guarantee of visibility in every zoomed context | 21.3 |
| Cluster | Wraps indeterminate groups the way words wrap | Semantics or grouping | 21.3 |
| Sidebar | Two-element arrangement responding to container width | Semantics or landmark | 21.3 |
| Switcher | Switches axis at a container-width threshold | Semantics | 21.3 |
| Cover | Vertical centring with a minimum height | Semantics | 21.3 |
| Frame | Constrains media by aspect ratio | Alternative text or media semantics | 21.3 |
| Grid | Wraps self-contained items by content-driven measurement | Semantics, and no basis for the clause 22 exception | 21.3 |
| Reel | Horizontally scrolling container that acknowledges its overflow | Guarantee that overflowed content is otherwise reachable | 21.3 |
| Imposter | Overlay geometry that cannot trap its own content | Focus trap, modal semantics, focus return | 21.3 |
| Icon | Sizes an icon relative to the text beside it | Accessible name or meaning | 21.3 |
Clause 21.3 says which column matters: "The right-hand column is the operative one." A layout primitive that silently omits semantics invites a developer to assume semantics were handled, and the omission is only safe when it is declared — Stack supplies vertical rhythm and not list semantics, so a consumer stacking list content supplies the list semantics itself (clause 21.3). For a tester, that column is the checklist: for each primitive in the package, open its Part II specification and confirm the non-supply declaration is there before any component that composes it is reviewed. Two primitives carry additional obligations.
Grid. A Grid arranges self-contained items and creates no header-to-cell relationship. Clause 11.2 already forbids every package, profile or not, from resting an exception rationale on a layout technique, and what the profile adds is a named consequence: the Grid primitive declares in its own specification that it supplies no basis for the claim (clause 21.3).
Reel. Every item in a Reel is independently readable within 320 CSS pixels, so that a user scrolls in one direction to reach an item and not in two directions to read one, and content that leaves the visible region remains reachable (clause 21.3).
Composition rather than configuration options
Composition, rather than increasingly capable individual components, produces the interface, and a package claiming this profile does not resolve a layout need by adding configuration options to an existing primitive where composing two primitives would serve (clause 21.3).
This is the rule that keeps a primitive set from turning into a widget library; the first time somebody proposes a variant prop on Stack, the clause is the answer.
Delineating surfaces under forced colours
A surface described only by a background colour can vanish in a forced-colours mode, because the mode may replace author backgrounds with system ones (clause 21.4).
Every delineated surface in a package claiming this profile therefore carries a transparent outline with a negative offset in addition to any background colour (clause 21.4).
The outline is invisible in normal rendering, occupies no layout space, and becomes visible when a forced-colours mode assigns it a system colour.
The accepted cost is stated rather than hidden: outline is no longer available for unrelated surface decoration, and every surface carries a declaration whose purpose is invisible in normal use (clause 21.4).
Then the part that is easiest to skip and hardest to fake: a package claiming this profile inspects every delineated surface in a forced-colours mode, and records the result as evidence under clause 16 "rather than as an assertion believed to pass" (clause 21.4).
Applying the technique is not the requirement; looking at the result and dating the observation is the requirement, and Section C covers the shape of a clause 16 evidence record.
The media-query policy
A package claiming this profile does not use layout media queries (clause 21.5).
Preference queries are permitted, and clause 21.5 states that these four "are the only permitted queries":
| Query | Status under clause 21.5 |
|---|---|
prefers-reduced-motion | Permitted |
prefers-color-scheme | Permitted |
prefers-contrast | Permitted |
forced-colors | Permitted |
| Any layout media query (viewport width, height, orientation, aspect ratio) | Forbidden |
No media query is required by clause 21: the four preference queries are permitted, not mandatory, and a package claiming this profile that uses none of them is not thereby deficient, because clause 21.4's forced-colours obligation is a requirement about surfaces and evidence, not a requirement to write a forced-colors query.
The distinction the clause draws is that a preference query asks what the user has asked for, while a layout media query asks how wide the viewport is and then guesses what that implies, and viewport width does not reliably indicate available space (clause 21.5).
Styling tiers and encapsulation
Styles in a package claiming this profile are organised so that reach is inversely proportional to specificity: universal and inherited styles first, layout primitives second, utilities last (clause 21.6).
Three consequences follow, all from clause 21.6.
A component does not restate an inherited font-family, color or line-height, because restating an inherited value breaks the inheritance chain that the user's own settings and stylesheets travel down.
Utilities are final adjustments and are not introduced before a need exists, and utility-first, breakpoint-prefixed layout is prohibited, because it encodes a viewport assumption into each individual element and so contradicts axiom 3.
The no-Shadow-DOM decision
Layout primitives in a package claiming this profile do not use Shadow DOM (clause 21.6).
That is an unusual position for a component library, so the clause records three grounds.
A shadow boundary complicates the relationships accessible names and descriptions depend on, including aria-labelledby, aria-describedby, aria-controls and the for attribute; encapsulation can prevent a user stylesheet or a forced-colours override from reaching the content inside it; and light DOM permits build-time primitive styles, which is what allows axiom 5 to hold.
The accepted cost is exposure to global style leakage, and the profile accepts it on the grounds that inherited and user styles have to be able to reach primitive content: "an encapsulation boundary that blocks a user's own stylesheet has defeated a mechanism the user relies on" (clause 21.6).
One correction to the earlier edition of this guide, which said primitives are "native custom elements without Shadow DOM": clause 21.6 prohibits Shadow DOM in layout primitives and says nothing about custom elements, so whether you implement a primitive as a custom element, a class, or a utility is an implementation choice rather than a profile requirement.
The eleven checks for this profile
The earlier edition of this guide carried a list of eleven rules whose count matched clause 21 and whose set did not: it omitted the 60ch measure, the Shadow DOM prohibition, the styling-tier ordering, the inherited-property rule, the forced-colours evidence record, the Reel 320-pixel obligation and the composition rule.
It included "DOM order matches visual order", which has no basis in clause 21, and "no spacing or font sizes outside the modular scale", which is clause 23.2 — a different profile, claimed separately.
The list below is derived from clauses 21.2 to 21.6, and these are the checks that arrive with a claim of afds-layout-intrinsic.
| # | Check | Clause |
|---|---|---|
| 1 | The measure never exceeds 60ch, subject to the documented per-container exception mechanism of clause 23.3 | 21.2 |
| 2 | Every dimension is user-relative; author-fixed dimensions appear nowhere except hairline borders, and smallness is not accepted as a justification | 21.2 |
| 3 | Layout responds to available space rather than viewport width | 21.2 |
| 4 | No element is given a fixed height | 21.2 |
| 5 | Layout is complete with JavaScript disabled, even where interaction requires it | 21.2 |
| 6 | No layout media queries; only the four preference queries appear | 21.5 |
| 7 | Every primitive present has a Part II specification declaring the semantics it does not supply, and the Grid primitive declares in advance that it founds no clause 22 exception claim | 21.3 |
| 8 | Every Reel item is independently readable within 320 CSS pixels, and content leaving the visible region stays reachable | 21.3 |
| 9 | A layout need is met by composing two primitives, not by adding configuration options to one | 21.3 |
| 10 | Every delineated surface carries a transparent outline with a negative offset, is inspected in a forced-colours mode, and the result is recorded as evidence under clause 16 | 21.4 |
| 11 | Styles are ordered so reach is inversely proportional to specificity; no component restates an inherited font-family, color or line-height; utilities come last; layout primitives use no Shadow DOM | 21.6 |
What this profile does not settle — afds-layout-intrinsic
The profile has one known unresolved conflict and clause 21.7 states it "MUST NOT be read as having resolved it".
Advisory technique C34 un-fixes a sticky header using media queries, so that sticky content does not obscure focus or consume reading space at high zoom, and clause 21.5 prohibits layout media queries, so the advisory remedy is unavailable under this profile.
Until a container-driven equivalent is designed, a package claiming this profile uses neither position: sticky nor position: fixed (clause 21.7).
Read the framing carefully, because it is the difference between a claim and an admission — clause 21.7: "This is a deferral and not a finding."
The profile does not assert that sticky positioning is inaccessible; it records that it cannot currently implement the published remedy, and declines to ship the pattern without one.
There is an explicit way out, which the earlier edition omitted: "A package needing sticky positioning should not claim this profile, and should record its own approach and evidence" (clause 21.7) — so if your product needs a sticky toolbar, decline afds-layout-intrinsic and document what you did instead rather than arguing with clause 21.5.
The profile also does not settle whether the 60ch measure applies inside a region claiming the clause 22 exception, is reduced there, or is suspended there, and the same question is recorded identically in clauses 22.7 and 23.7 (clause 21.7).
Do not present the sticky deferral as the profile's answer to Success Criterion 2.4.11 Focus Not Obscured: clause 21 makes no such claim, and turning a deferral into a criterion answer is the kind of overstatement clause 21.7 exists to prevent.
Where this profile's ideas came from — afds-layout-intrinsic
The intrinsic-layout argument, the axiomatic framing, the composable single-purpose primitive approach, and the twelve primitives are adopted from Every Layout: Relearn CSS layout by Heydon Pickering and Andy Bell, at every-layout.dev (clause 21.8).
So are the 60ch measure, the modular scale generated by successive calc() from a 1rem root, the Stack primitive's adjacent-sibling relationship, the Switcher primitive's container-width threshold, and the transparent-outline treatment for forced colours.
The adjacent-sibling selector * + * that Stack rests on was introduced as the "lobotomized owl selector" by Heydon Pickering in Axiomatic CSS and Lobotomized Owls, A List Apart, 21 October 2014, at axiomatic-css-and-lobotomized-owls, and the reasoning that margin is a relationship between adjacent elements rather than a property of an element belongs to that article — a point the earlier edition of this guide made while attributing it to nobody.
Every Layout is a commercial publication, and clause 21.8 records that the profile describes the method and attributes it, reproduces neither the source text nor the source code, and directs a reader wanting the original reasoning to the authors' work.
Three things the profile changed (clause 21.8). Every Layout names a thirteenth primitive, The Container, which this profile does not adopt — so if you have read the source work and expect thirteen, twelve is deliberate. The prohibition on layout media queries is absolute here, which is stricter than the source work requires, and the requirement that every primitive declare the semantics it does not supply is an application of the Part II disclosure obligation rather than a requirement of the source work.
Six things originate here and rest on the project's own reasoning (clause 21.8): the Shadow DOM prohibition and its three grounds; the forced-colours inspection-and-evidence requirement; the prohibition on a Grid-primitive region founding a two-dimensional exception claim; the Reel 320-pixel reading of technique G225; the sticky and fixed deferral; and the requirement that primitives be tested at 400% zoom, in forced colours, at a doubled root font size, under text-spacing overrides, and inside realistic pages rather than in isolation alone.
The scoped reflow profile — afds-reflow-scoped
The earlier edition of this guide wrote its reflow material as project-wide rules and never named this profile at all, which inverted the structure twice over: it made a declinable profile look universal, and it blurred the line between the parts of reflow that bind every package and the parts that arrive only with a claim. Get the split right first.
Core, binding on every package. The reflowBehaviour object of clause 11.1 and its seven required entries, and the rule in clause 11.2 that an exception rationale rests on semantic two-dimensional structure and never on visual appearance or on the layout technique used to produce it.
Section C covers both, and the fields are not repeated here; Success Criterion 1.4.10 Reflow itself, and its test conditions, are WCAG's, described there too.
This profile, arriving only with the claim. Everything in clauses 22.3 to 22.6: what a claim has to record, where the scroll is allowed to reach, how cells and their surroundings behave, and which environment values a reflow assertion carries. Clause 22.2 is explicit about its own status: it explains how the core test resolves in practice, "because the test is easy to state and routinely misapplied", and then says of itself, "This clause adds no requirement."
The profile's statement is two sentences (clause 22.1):
Two-dimensional scrolling is permitted only where the content's meaning genuinely requires two axes, is justified by naming those axes, and is confined to the element that needs it. It never reaches the page.
When the exception genuinely applies
A region qualifies when a cell's significance depends on its relationship to both a row axis and a column axis, so that flattening the structure would destroy meaning rather than merely rearrange appearance (clause 22.2).
A CSS Grid container has no table semantics: declaring display: grid, or wrapping items with a content-driven measurement, creates no row header, no column header and no header-to-cell relationship, so visual grid arrangement is not offered as a basis for the exception, and the clause records how the test resolves for common cases (clause 22.2).
| Content | Basis | Excepted |
|---|---|---|
| Results table with genuine row and column header relationships | A cell's significance depends on both axes | Yes, as a scoped region |
| Programme guide organised by channel and time | Channel and time are both meaning-bearing axes | Yes, as a scoped region |
| Collection of self-contained cards | Arrangement is presentational | No |
| Dashboard laid out in grid areas | Arrangement is presentational | No |
| Filter panel beside a results list | Adjacency is convenience, not meaning | No |
The programme-guide row establishes that a meaning-bearing two-dimensional structure need not be a conventional data table, and clause 22.2 immediately fences that off: it "MUST NOT be read as extending the exception to visual grids generally".
Two limits on this table are worth stating, because clause 22.8 states them. The reading that the exception rests on a semantic relationship rather than a visual arrangement is this project's analysis of the criterion's wording — "a defensible reading and it is not a W3C ruling" — and the table itself is the project's application of that reading to cases the Working Group has not adjudicated.
The four records a claim has to carry
Clause 11.2 requires a rationale resting on semantic two-dimensional structure, and this profile makes that rationale specific: a component or region in a package claiming the profile does not claim the two-dimensional exception without recording all four of the following in its component specification (clause 22.3).
| # | Record | Clause |
|---|---|---|
| 1 | The identification of both meaning-bearing axes | 22.3 |
| 2 | An explanation of how a cell's significance depends on each axis | 22.3 |
| 3 | A statement of the semantic structure that carries the relationship, which has to be a table structure or an ARIA grid structure and may not be a purely presentational arrangement | 22.3 |
| 4 | The boundary of the excepted region, so that a tester knows what is inside the claim and what is outside it | 22.3 |
The earlier edition of this guide covered the first two and dropped the last two, which are the ones a tester actually works from. "It is displayed as a grid" is not recorded as a justification, and clause 22.3 states that a specification offering it does not conform. A region needing the exception needs semantic structure first, and where it is absent, clause 22.3 says the correct response is to supply it or to abandon the claim; changing a role in order to qualify is already forbidden by clause 11.2 and is not restated as a profile requirement.
Scoping the scroll
An excepted region is placed in its own scrollable container, and two-dimensional scrolling does not reach the page in a package claiming this profile (clause 22.4).
Clause 22.4 labels itself honestly: page-level bidirectional scrolling can conform where the content is genuinely excepted, "so this requirement is stricter than the criterion". The profile adopts it anyway, on a usability argument of the project's own — a page-level horizontal scrollbar tells a user that content exists off-screen everywhere, when in fact it exists in one region, and the user is left searching for material that is not there — and clause 22.8 confirms that reason "is a usability argument of this project's own and is not a WCAG requirement". Scoping the scroll also lets every surrounding part of the page reflow normally, which is what clause 22.5 requires.
Cells and the content around them
The exception applies to the excepted region and to nothing else (clause 22.5). A heading introducing an excepted region, its surrounding prose, a search field, filter controls, pagination, and any other adjacent interface reflow as ordinary content and are tested as ordinary content (clause 22.5).
An individual cell meets the criterion as ordinary flow content, unless it contains material that independently requires two-dimensional presentation for usage or meaning (clause 22.5). The WCAG qualification "not individual cells" marks where the semantic relationship stops: the table needs both axes to mean what it means, and one cell's content does not.
Four obligations follow for cell content, all from clause 22.5. A long selector, a URL, a failure description, and a code excerpt appearing in a cell either wrap at 320 CSS pixels or provide a mechanism by which a user can reveal the complete value. A truncated string is not the only presentation of a value, and truncation is permitted only where a user can reveal the complete value or reach a complete alternative presentation — the earlier edition of this guide covered wrapping and never addressed truncation at all, which left the most common real-world shortcut unexamined. Content does not disappear on reflow without remaining reachable. Where indentation carries meaning, as in nested lists and code, it is reduced under magnification rather than removed — reduce, not preserve-with-exceptions. Whether a particular code cell may wrap or must preserve non-wrapping indentation is a component-level judgement, and clause 22.7 records that the profile does not settle it.
The four values every reflow assertion carries
A package claiming this profile records, for every reflow assertion, the device, the browser, the starting viewport, and the zoom level at which the observation was made or is to be made (clause 22.6).
Clause 22.6 gives the reason plainly: a reflow result without those four values is not interpretable, because "no content is clipped" is a different statement at a 320 CSS pixel viewport than at a 1280 by 1024 starting viewport with 400% zoom applied. For a tester this is the single highest-value line in the clause — an assertion missing any of the four is not a weak result but an uninterpretable one.
The published techniques this profile relies on
Clause 22.6 names eight W3C techniques for WCAG 2.2 and cites them as published; the techniques index is at WCAG22/Techniques.
| Technique | Use under this profile | Clause |
|---|---|---|
| C31, Flexbox to reflow content | Primary mechanism for the Cluster, Sidebar and Switcher primitives | 22.6 |
| C33, Reflow with long URLs and strings | Required in table cells | 22.6 |
| C38, Width, max-width, and Flexbox for labels and inputs | Required for filters and forms | 22.6 |
| SCR34, Sizes and positions scale with text | Satisfied by the modular scale of clause 23.2 | 22.6 |
| G224, Meaningful indentation and Reflow | Required wherever indentation carries meaning | 22.6 |
| G225, Horizontally scrolling panels fit 320 CSS pixels | Required for Reel items, read strictly per clause 21.8 | 22.6 |
| G206, Layout alternative without horizontal scrolling | Permitted enhancement for an excepted region; not required | 22.6 |
| C34, Un-fix sticky headers with media queries | Unavailable under afds-layout-intrinsic; see clause 21.7 | 22.6 |
Two of those rows carry cross-profile consequences: SCR34 is satisfied by the scale of clause 23.2, which belongs to afds-typography-colour — a package claiming afds-reflow-scoped alone has to satisfy SCR34 some other way or record that it does not — and C34's unavailability is a consequence of clause 21.5, so it only bites a package that also claims afds-layout-intrinsic.
One point of precision about C31: clause 22.6 notes that it is a sufficient technique for Success Criterion 1.4.10 rather than a statement of compatibility with it, so a package building composition from Flexbox is implementing a technique the Working Group deems sufficient, which the clause calls "a stronger position than asserting that the criterion is met".
What this profile does not settle — afds-reflow-scoped
Success Criterion 1.4.4 Resize Text requires text to be resizable to at least 200%, and it does not require a specific amount of text enlargement at the test condition of Success Criterion 1.4.10. Clause 22.7 records that a 200% zoom producing a viewport smaller than that test condition "is not for that reason alone a failure of 1.4.10" — a distinction the profile records without relying on it to excuse anything.
Three questions remain open, and clause 22.7 states that a package claiming this profile "MUST NOT represent them as answered":
- whether an excepted region should also offer a user-selectable alternative presentation without horizontal scrolling, under technique G206;
- when code inside a cell needs preserved non-wrapping indentation and when it must wrap;
- whether the 60ch measure applies inside an excepted region, is reduced there, or is suspended there.
Two corrections kept on the record
Clause 22.8 records two changes of mind, "because a reader is entitled to know the profile changed its mind". An earlier position in this project treated wide tables at 400% zoom as an unresolved weakness of its layout method, which was wrong: a table with genuine two-dimensional semantic relationships is excepted, and the real work is scoping the exception correctly. An earlier wording claimed the exception "covers grid-based UI generally", which was also wrong, conflating semantic grid structure with CSS Grid layout. Clause 22.8 also records what originates here: the reading in clause 22.2, the resolution table, the four records of clause 22.3, the prohibition on "it is displayed as a grid", the prohibition on a Grid-primitive region founding a claim, and the requirement that every reflow assertion record device, browser, starting viewport and zoom; it further records that clause 22.5's treatment of long strings in cells applies technique C33 as a requirement of this profile, where the technique itself is sufficient rather than required.
The typography and colour profile — afds-typography-colour
The earlier edition of this guide scattered this profile's material through its layout chapter, so a reader who declined the layout method could not tell that the scale, the measure and the contrast obligations were a separate, separately-claimable set — they are: you can claim afds-typography-colour and no other profile, or every other profile and not this one.
The statement is two sentences (clause 23.1):
Type and space are generated from one scale seeded at the user's own text size, so that changing that size moves the whole interface together. Colour reinforces meaning and never carries it alone.
One scale, anchored at 1rem
A package claiming this profile generates font sizes and spacing from a single modular scale, and five obligations come with that, all from clause 23.2.
The scale is anchored at 1rem, so that the user's own root font size is the seed for every derived value.
Each point on the scale is derived from the preceding point by calculation rather than chosen independently.
Body text uses a line height of 1.5.
The largest and smallest text on one surface do not differ by more than 3:1.
A font-size or spacing declaration references a scale value, and a literal value is not used.
Clause 23.2 explains why the shared seed matters more than the individual numbers: because type, gaps and padding all derive from the same root, "a user who raises the default text size gets a proportionally larger interface rather than larger text crammed into unchanged spacing". One line of body text is the natural denominator for vertical rhythm, which is why the line height and the scale ratio are the same number — 1.5 in both cases. The accepted cost is stated: available sizes are few and widely separated, and display typography is constrained (clause 23.2).
A worked scale, for illustration only:
{
"scale": {
"step--1": "0.75rem",
"step-0": "1rem",
"step-1": "1.5rem",
"step-2": "2.25rem"
}
}
Each step is the previous one multiplied by the ratio, and spacing tokens are aliases of scale steps rather than independent values — which is what "MUST reference a scale value" (clause 23.2) means in practice.
Building from the browser default rather than setting a floor
A 16px minimum is widely repeated as a rule for interface text, and it is worth being exact about what it is, because the specification states no minimum text size anywhere and a reader may take that for an omission.
No accessibility standard sets a 16px floor. WCAG 2.2 specifies no minimum text size in absolute units at all. Its requirement about text size is Success Criterion 1.4.4 Resize Text, which asks that text, apart from captions and images of text, "can be resized without assistive technology up to 200 percent without loss of content or functionality", from W3C, Web Content Accessibility Guidelines (WCAG) 2.2, at TR/WCAG22, and discussed in the specification at clause 22.7. The 18 point and 14 point bold sizes in the WCAG glossary define large-scale text for the contrast criteria and are not a general floor either.
What 16px is, is the default root font size in an unmodified browser.
The accessible practice built on that default is to express every size relative to it, in rem, so that a user who changes the default carries all derived values with them.
That is exactly what clause 23.2 does when it anchors the scale at 1rem, "so that the user's own root font size is the seed for every derived value".
So the figure and the specification are not in tension, and no floor clause is missing.
Anchoring at 1rem is the practice, expressed in the only terms that survive a user changing the default.
Writing 16px into a token would abandon it, because the number would stop tracking the user's choice at the moment they made one.
The provisions that do constrain text are the 1rem anchor and the 3:1 on-surface ratio, both in clause 23.2, and neither is a floor in absolute units.
The measure
The measure is line length expressed in characters, and a package claiming this profile does not allow it to exceed 60ch (clause 23.3).
The cap is applied exception-based: content is capped broadly, and deliberate exceptions are named per container rather than granted by default (clause 23.3). An exception has to be documented, and clause 23.3 states the consequence in five words: "an undocumented exception fails review". That is the sentence to put in front of a designer who wants a wider container for one page.
The measure is expressed in ch or another font-relative unit and is not expressed as an author-fixed width, because a character measure cannot be guaranteed by a pixel width: the number of characters that fits in a fixed width changes as the font size changes (clause 23.3).
Because 1ch varies with font size, text at different sizes occupies different proportions of the same wide container, and clause 23.3 says that is a consequence of the axiom rather than a defect.
One relationship to keep straight, because it is easy to assume one obligation discharges the other. The measure axiom and Success Criterion 1.4.10 approach one concern from opposite directions: the axiom limits line length positively, as a typographic commitment, and the criterion prevents unbounded line length under magnification, as a floor (clause 23.3). Clause 23.3 adds the sentence the earlier edition of this guide omitted — "Satisfying one does not satisfy the other" — and clause 23.8 records that the observation originates with the project.
Colour does not carry meaning alone
In a package claiming this profile, status, severity, and any other meaning conveyed by colour is also conveyed by text or by shape, colour is reinforcement only, and an unlabelled colour-coded severity scheme is not used (clause 23.4).
Clause 23.4 gives two independent reasons, and says either alone would justify the requirement. A colour-only encoding is unavailable to users whose colour vision does not distinguish the chosen hues, and it is also unavailable to any user in a forced-colours mode, because the mode may replace the author's palette entirely, and a distinction carried only by hue does not survive that replacement. The accepted cost, in the clause's own words: interfaces look plainer.
For a designer, the practical test is to render the interface in greyscale and then in a forced-colours mode; anything that stops being distinguishable was carrying meaning by colour alone.
Contrast: a declared level and per-pair records
This profile sets its default target level under clause 12.4 at Level AA (clause 23.5).
A component in a package claiming this profile may amend that default under clause 12.4, upward or downward, and amending it is recorded with a reason (clause 23.5). Clause 12.4 sets the resolution order: a component's own declaration, then the default set by a claimed method profile, then the package default, with the first available declaration governing.
The profile is not to be read as fixing a contrast ratio independently of the declared level: the applicable ratios are those WCAG 2.2 attaches to the effective target level, and clause 23.5 declines to restate them because doing so "would duplicate WCAG and would go stale when WCAG does not" — so do not look for a number in clause 23.5; there deliberately is not one.
Why AA rather than AAA, when AAA looks more rigorous? A profile-wide AAA default would set a threshold the project has not established is usable across data-dense reporting surfaces, and "a default that packages routinely amend downward is a worse instrument than a default they can honestly hold" (clause 23.5). AAA remains available and is expected to be the right amendment for many components, which is why clause 12.4 makes amending upward as ordinary an act as amending downward, and clause 23.8 grounds the choice further: WCAG 2.2's own Conformance section states that "It is not recommended that Level AAA conformance be required as a general policy for entire sites because it is not possible to satisfy all Level AAA success criteria for some content", at TR/WCAG22.
What the profile does require, independently of the level, is that the claim be measured per pair: a package claiming this profile records, for each foreground and background token pair it treats as valid, the measured ratio and the effective target level that pair was measured against (clause 23.5).
A palette-level claim is not recorded in place of per-pair records, because contrast is a property of a pair and not of a set: "a claim about a palette is not checkable, and a palette that satisfies a threshold in most combinations satisfies nothing in particular" (clause 23.5) — a brand palette expressed purely as tokens is a set of pairing candidates, not a set of verified pairs.
There is a gap here the profile cannot close, and it says so: design token formats carry values and have no standard expression for the statement that one foreground token is valid on one background token at a given threshold (clause 23.5). Until such an expression exists, a package claiming this profile carries its verified pairs as assertions under clause 15, with evidence under clause 16, rather than expecting the token file to express them (clause 23.5) — Section C covers the shape of both records.
Clause 23.8 records that the per-pair requirement and the prohibition on palette-level claims originate with the project: "WCAG requires a ratio to be met and does not say where the measurement is recorded, so the per-pair record is this project's requirement."
Declaring the typefaces a package depends on
A typeface is treated the same way as a target level: declared by the author, not mandated by the profile, and the profile is not to be read as requiring a particular typeface or setting a default one (clause 23.6).
Three declarations arrive with the claim (clause 23.6). A package claiming this profile declares the typefaces it depends on, and declares whether the interface remains usable when they are unavailable. A component may declare a typeface dependency of its own, and one that does records why the package default is insufficient for it.
The second of those is the one teams skip: "which font do we use" is a design decision; "does the interface still work when the webfont fails to load" is an accessibility disclosure, and clause 23.6 asks for it in writing.
No default is set because the project has not settled one, and Atkinson Hyperlegible, published by the Braille Institute, is under consideration and has not been adopted (clause 23.6). Clause 23.8 records what is known about it: the family is published at freefont, is offered in three versions, and the original typeface was introduced in 2019. It also records a discrepancy it declines to resolve — the download page and the release announcement of 10 February 2025 differ on the name of the monospaced member, which the download page calls Mono and the announcement calls Monospace, at brailleinstitute.org — and were the typeface adopted later, clause 23.6 notes the mechanism already exists: the profile would name it as its default and packages would remain free to amend.
The media-query position for this profile
Clause 23 imposes no media-query policy of its own, and the permitted, forbidden and required queries listed in D.5 come from clause 21.5 and bind only a package claiming afds-layout-intrinsic, so a package claiming afds-typography-colour and not the layout profile is under no clause-21 restriction on media queries at all.
Forced colours reaches this profile from a different direction: clause 23.4's second reason for the colour-not-alone rule is forced-colours replacement of the author palette, so a package claiming this profile has a stake in forced-colours behaviour even without the surface-delineation obligation of clause 21.4, whose outline, inspection and evidence record arrive only with the layout profile.
If you claim afds-typography-colour alone, test in a forced-colours mode anyway — clause 23.4's requirement is unverifiable without it — but do not cite clause 21.4 as your basis.
What this profile does not settle — afds-typography-colour
The profile sets a default target level of Level AA and sets no default typeface, and clause 23.7 states that neither is a finding about what is sufficient for users. Three questions are open (clause 23.7).
- whether the project should raise its own default to Level AAA, and whether the 7:1 ratio Level AAA attaches to body text remains usable on data-dense reporting surfaces — clause 23.7 notes what is settled, that the answer is a declaration and not a requirement of the specification, so the question can stay open without blocking a package from conforming;
- whether the profile should name a default typeface, and whether that typeface should be Atkinson Hyperlegible;
- whether the 60ch measure applies inside a region claiming the clause 22 exception, recorded identically in clauses 21.7 and 22.7.
Where this profile's ideas came from — afds-typography-colour
The 60ch measure, the modular scale generated by successive calculation from a 1rem root, and the practice of deriving spacing and type from one seed are adopted from Every Layout: Relearn CSS layout by Heydon Pickering and Andy Bell, at every-layout.dev (clause 23.8).
A line height of 1.5 for body text corresponds to the line-height value that Success Criterion 1.4.12 Text Spacing requires content to tolerate, at TR/WCAG22, and that is also the source of the 1.5 text-spacing ratio: the number is WCAG's tolerance figure, adopted here as a positive commitment rather than as a tolerance, and the requirement that sizes and positions scale with text is consistent with W3C technique SCR34 for WCAG 2.2 (clause 23.8).
Clause 23.8 is unusually careful about what the profile does not claim. The reasoning that over-long lines make it harder to track from one line to the next, and that this bears particularly on users with dyslexia, low vision or attention-related disabilities, is described as the standard argument for a measure cap in typographic practice: "This profile asserts no research finding of its own on the point and quantifies no benefit." The conformance levels are WCAG 2.2's, and "This profile defines no level, no ratio, and no threshold of its own."
One number in the clause has no published source at all. The 3:1 limit on the ratio between the largest and smallest text on one surface originates with the project, and rests on the argument that a screen-magnifier user should not have to change zoom repeatedly when moving between a heading and the body copy beneath it. Clause 23.8: "A reader who wants to challenge one number in this clause should challenge this one." The earlier edition of this guide presented the 3:1 figure without that caveat, which made an asserted opinion look like settled practice. Clause 23.3's requirement that the measure cap be applied exception-based with documented per-container exceptions is likewise a process requirement of the project and not a requirement of the source work (clause 23.8).
The native-first pattern profile — afds-patterns-native-first
This is adopted, normative policy: the open-questions register records G2, "Adopting APG by reference", as Settled, 2026-09-01 — native HTML first, and published patterns adopted by reference rather than copied.
The specification carries it as the afds-patterns-native-first profile at clause 24, and the sample package claims that profile.
The earlier edition of this guide described the policy as "proposed and not yet adopted" and said the five statuses were "proposed", and both statements were stale. The five-status vocabulary is core, at clause 9.2, and binds every package whether or not it claims this profile; the native-first preference is a normative statement of this profile.
The profile's statement has five clauses (clause 24.1):
WCAG establishes the required outcome. Native HTML is preferred. ARIA fills genuine semantic gaps. A published pattern guide supplies the interaction model for recognised custom patterns. The package specifies, tests, versions, and evidences the implementation actually shipped.
Note the order, and keep it (clause 24.1). The normative outcome sits first, because a disagreement about behaviour then resolves against an outcome rather than against a preference; the second clause sets the default engineering answer, because native elements arrive with focus behaviour, activation semantics, disabled-state handling and forced-colours treatment already implemented and already tested by browser vendors. The third confines ARIA to the repair role it was designed for, and the fourth admits that some interactions have no native equivalent and that a custom one should behave the way users already expect. The fifth locates responsibility, "because no external document can carry evidence about the code a package actually ships".
Clause 24.8 adds a constraint on how you cite the statement: it is this project's formulation, no external body states it, and it "MUST NOT be attributed to the W3C or to any working group".
The status names changed — use the current ones
Clause 9.2's five values are native-first, pattern-derived, pattern-adjacent, custom and prohibited.
Earlier drafts in this project named two of them after the ARIA Authoring Practices Guide specifically — APG-derived and APG-adjacent — and clause 24.8 records that they were renamed "so that the core vocabulary of clause 9 does not presuppose one pattern guide".
The old names are retired: if you have met them in the earlier edition of this guide, in a component specification, or in a registry, they should be updated to pattern-derived and pattern-adjacent.
There is a related prohibition that reaches every package, profile or not: clause 4.4 states that a package "MUST NOT claim that a component conforms to the ARIA Authoring Practices Guide, because that guide is informative and has no conformance model to conform to", and clause 24.7 recalls it informatively because this profile is where the temptation arises. The publishable claims about a component are the accessibility criteria met, the semantics used, and the recorded assistive-technology results (clause 4.4), and the sentence "this component conforms to the APG" is never published as an accessibility claim.
The pattern registry
Clause 9 already requires every component to declare a derivation.status from the five values, and already imposes the extra obligations pattern-adjacent and prohibited carry; none of that is restated in clause 24, and a package that claims no profile is bound by all of it (clause 24.2).
What this profile adds is a package-level artefact: a package claiming this profile carries a registry listing every component and pattern in the package against its status (clause 24.2).
Part IV fixes its location — the registry sits at patterns/registry.json, is declared in patterns.canonicalSources with role canonical, appears in the inventory, and no package uses that path for anything other than a registry satisfying clause 24.2, whether or not it claims the profile (clause 29.4).
Two rules govern its contents.
The registry does not disagree with any component's own declaration, and where the registry and a component specification differ, the component specification governs and the package is defective (clause 24.2) — that is the resolution order to encode in a validator: component first, registry second, and a mismatch is a defect rather than a question.
The registry also records a prohibited entry for a pattern the package has declined, even though no component implements it (clause 24.2).
Clause 24.2 says that last requirement is the reason the artefact is worth having, because a decision not to build something leaves no component behind to declare it, and without a package-level registry a prohibition is invisible: "the absence of a menubar component looks identical to nobody having considered a menubar, and the argument gets held again in the next review".
Clause 9.2 adds the shape of that no: a prohibited entry states the cost that motivated the prohibition and is revisitable if the underlying support picture changes.
Choosing native first
The rule is stated as a restriction rather than as an endorsement, because clause 24.3 identifies the likeliest failure mode for a system that admires a pattern guide: turning every familiar interaction into a custom widget.
Use native HTML when it provides the needed semantics and interaction. Adopt a published pattern only when a genuinely custom composite widget is required.
| Product need | Preferred response | Why |
|---|---|---|
| Action | Native <button> | Activation, focus, disabled state, and keyboard behaviour are already provided |
| Choice between options | Native radio or checkbox inputs | Avoids recreating form semantics |
| Navigation | Links inside a navigation landmark | Do not convert site navigation into a menu widget |
| Reveal supplementary content | Native <details>, or a button with controlled content | Often avoids a full custom disclosure implementation |
| Modal confirmation | A dialog component following the published dialog model | A genuine composite interaction with focus-management needs |
| Rich autocomplete | A combobox, only where native controls cannot satisfy the task | High complexity; semantics and keyboard contract must be complete |
| Large interactive results table | A native table first; an ARIA grid only where directional cell navigation is genuinely needed | A visual CSS grid is not a semantic grid and does not justify the clause 22 exception |
The rows are ordered from cheapest to most expensive, and that is the only ordering claim the clause makes; the earlier edition of this guide reordered the table and asserted that the first four rows "account for the large majority of interactive surface", a claim that appears nowhere in clause 24.3 and should not be repeated.
The operative obligation is stated at full strength: in a package claiming this profile, a component is not given a pattern-derived status where a native element in this table would have supplied the semantics and interaction, unless the component specification records why the native element was insufficient (clause 24.3).
Not "should probably be native-first" — the specification puts this at MUST NOT strength, and it is this profile's single operative addition to the Part II disclosure duty, which requires a package to record the native baseline it considered where this profile requires it to prefer that baseline.
Clause 24.8 records that this rule originates here, and describes it as "the design rule that Part II deliberately declined to impose".
Reviewing a derived component: twelve items
Clause 24.4 is informative and creates no requirement; it exists because reviewing a derived component means checking twelve things distributed across eight core clauses, and a reviewer working from the core alone reassembles the list every time, in practice incompletely. Every item below is required by the clause named beside it, not by this profile, and because clause 20.1 forbids a profile from restating a core requirement, removing this profile's claim removes none of these obligations (clause 24.4).
| # | Review item | Required by |
|---|---|---|
| 1 | The published pattern it derives from, with its source URL | 9.3 |
| 2 | The native alternative considered, and why it was insufficient | 9.3 |
| 3 | Every deviation from the pattern, with reason and cost | 9.3 |
| 4 | Whether the pattern is support-dependent, and its reassessment trigger | 9.3, 9.5 |
| 5 | The semantic model | 8 |
| 6 | The keyboard contract | 10 |
| 7 | The focus lifecycle | 10.4 |
| 8 | Pointer and touch parity, and speech-recognition operation | 10.2 |
| 9 | Reflow behaviour, and any two-dimensional exception claim | 11, 11.2 |
| 10 | The WCAG success criteria the component affects | 12 |
| 11 | Assistive-technology evidence for its claims | 16 |
| 12 | Its guarantees, non-guarantees, and recorded uncertainty | 14, 17 |
A specification missing any of the twelve is incomplete under the core, not under this profile (clause 24.4). The earlier edition of this guide gave ten of these and implied closure, dropping items 3, 4, 9 and 12 — the deviation record, the support dependency, the reflow behaviour and the guarantee set. One count to keep separate: these twelve review items are written for engineering review, and they are not the eleven design-tool annotation fields of clause 19, which are written for design handoff — clause 24.4 says the two lists "overlap in subject and differ in audience, count, and purpose, and a count of one is never a count of the other".
Two cautions, and a correction to the earlier guide
Clause 24.5 carries two cautions the profile judges strong enough to sit in the profile itself, and one of them corrects the earlier edition of this guide.
Menu and menubar are not for ordinary navigation or action lists
Read the first half of this caution before the second, because the earlier edition of this guide got the first half wrong. The published menu and menubar pattern is not restricted to application menus, and the pattern guide ships a navigation menubar example demonstrating site navigation (clause 24.5). Clause 24.5 draws the conclusion in its own words: "Using a menubar for site navigation is therefore a sanctioned use of that pattern and MUST NOT be described as a misuse of it", and clause 24.8 repeats it from the other direction: "the APG sanctions the use this profile declines."
The earlier edition of this guide listed "converting site navigation into a menu widget" as a common mistake; that was a contradiction of clause 24.5, and if you have met that text, treat it as withdrawn. What clause 24.5 actually says is that the caution "stands as a convention of this profile with a stated cost, which is the honest form for it", and the cost is the whole composite contract: a roving-focus model, a single tab stop, author-managed arrow-key movement, submenu open and close behaviour, and a role that causes a screen reader to describe the thing as a menu rather than as navigation. The profile judges that cost unjustified where a list of links inside a navigation landmark already gives users a structure they know and costs nothing to maintain, and it notes that a list of buttons is usually an action group, with a toolbar the cheaper composite where one is genuinely warranted (clause 24.5).
There is an explicit route through: a package claiming this profile may nonetheless adopt a menubar, and if it does, the justification appears in the component's specification, tagged as a product-deviation under clause 13, with the keyboard contract written out in full (clause 24.5).
Clause 13 requires a product-deviation to record its cost as well as its reason, so the roving-focus contract above is the cost you write down.
An ARIA grid is not a remedy for visual density
A grid widget is justified by a need for directional cell navigation, and clause 24.5 states it "MUST NOT be justified by a table looking crowded or by a wish to avoid reflowing content". Where the underlying difficulty is that a wide table is hard to use at high zoom, the response is a scoped scroll container and a correctly justified exception under clause 22, and clause 24.5 states that the response "MUST NOT be a role change" — which closes a loop with clause 11.2, forbidding the adoption of a widget role in order to unlock the exception and telling a consumer encountering such a rationale to treat the package as defective.
One vocabulary note that saves confusion in review: "Grid" names three different things in this material — the CSS Grid layout module, the Grid layout primitive of clause 21.3, and the ARIA grid widget role — and only the third carries interaction semantics, while none of the three justifies the clause 22 exception on its own. Clause 24.8 records that the characterisation of the grid pattern as covering both tabular information and layout containers is the APG's own, the pattern being titled "Grid (Interactive Tabular Data and Layout Containers)" in the pattern index at apg/patterns.
The approved component catalogue and its gates
A package claiming this profile does not implement a pattern catalogue larger than the product needs, which is a prohibition rather than a preference and the first thing clause 24.6 says. The profile defines an ordered catalogue: priorities 1 to 5 may be adopted on judgement, and priorities 6 to 8 are not adopted without a recorded justification, recorded at the time the gate is passed rather than reconstructed later (clause 24.6).
| Priority | Pattern or primitive | Gate | Clause |
|---|---|---|---|
| 1 | Native button, link, checkbox, radio, text input, select | None | 24.6 |
| 2 | Disclosure | None | 24.6 |
| 3 | Dialog | None | 24.6 |
| 4 | Alert and status messaging | None | 24.6 |
| 5 | Native table with a scoped scroll container | None | 24.6 |
| 6 | Tabs | Recorded finding that persistent peer views improve a task | 24.6 |
| 7 | Combobox | Recorded finding that a large controlled vocabulary must be searched | 24.6 |
| 8 | Tree, treegrid, or ARIA grid | Recorded user research demonstrating the need | 24.6 |
The ordering is deliberate: priorities 1 to 5 consist almost entirely of native elements and one simple composite, and in an audit and remediation product they cover the core work, while priorities 6 to 8 carry complex keyboard and assistive-technology contracts, and each unused composite adds untested surface (clause 24.6).
One gate has a named prohibition attached: visual density is not recorded as the gate justification for priority 8 (clause 24.6), which is the same argument as the second caution in clause 24.5, closed off at the point where it would otherwise re-enter as a catalogue decision.
The "recorded at the time the gate is passed" wording matters for testers and auditors, because a justification written six months later, when somebody asks why the treegrid exists, does not satisfy the clause.
What this profile does not settle — afds-patterns-native-first
Clause 24.7 adds no requirement and recalls two clause 4.4 prohibitions informatively, because this profile is where the temptation to breach them arises: no package claims conformance to a pattern guide, and no producer presents a package claim as evidence that a service assembled from the package is accessible.
The catalogue in clause 24.6 is sized for an accessibility audit and remediation product, and clause 24.7 adds: "It is not a general recommendation, and a package with a different purpose should expect a different catalogue" — so do not read the eight priorities as a recommended component roadmap for an arbitrary product.
Whether any given project adopts this profile as a standing position is a matter for that project and not for the specification (clause 24.7); the profile defines what claiming it commits a package to and does not recommend that a package claim it. The open-questions register keeps related items live. G1 asks what user or task evidence admits a pattern to the catalogue and what removes one, noting that the priority order is "reasoned rather than evidenced". G2, though settled on the native-first policy itself, records as still open how a deviation from a pattern convention is recorded and reviewed: clause 13 gives the deviation a requirement kind and clause 24.5 requires a menubar adoption to be justified in the component specification, but no review process is attached to either; G3 records that no minimum assistive-technology matrix has been fixed per component.
Where this profile's ideas came from — afds-patterns-native-first
The interaction models, keyboard expectations and pattern definitions this profile refers to as published patterns are those of the W3C ARIA Working Group, ARIA Authoring Practices Guide (APG), at ARIA/apg, with the pattern index at apg/patterns (clause 24.8). The APG is informative and has no conformance model, which is why clause 24.7 prohibits claiming conformance to it and why the fifth clause of the statement places evidence in the shipping layer, and the scope statements about menu and menubar, including the navigation menubar example, are the APG's own, at patterns/menubar. The required outcomes the profile defers to are W3C, Web Content Accessibility Guidelines (WCAG) 2.2, at TR/WCAG22; the repair role assigned to ARIA reflects W3C, Accessible Rich Internet Applications (WAI-ARIA) 1.2, at TR/wai-aria-1.2; and the native elements preferred in clause 24.3 are those of WHATWG, HTML, Living Standard, at multipage.
Clause 24.8 also cites Putnam, Rose and MacDonald's study of accessibility in user-experience practice, in which design systems were the most frequently reported concrete action, at 10.1145/3575662 — and immediately notes that the study warns that concentrating responsibility in specialist teams risks abdication elsewhere, and that "this profile does not claim the paper endorses its approach".
Originating here (clause 24.8): the five-status vocabulary and the definitions of pattern-adjacent and prohibited, which were devised in this profile and have since moved into the core at clause 9 and are no longer this profile's to claim; the package-level registry artefact and the declined-pattern entry; the grouping of twelve review items; the native-preference rule of clause 24.3; the menubar caution as a project convention with a stated cost; the caution against an ARIA grid for visual density; and the catalogue, its ordering and its gates.
One correction is kept on the record (clause 24.8).
An earlier framing in this project treated the APG as the component layer of the design system, which was wrong in kind, because the APG describes patterns while a design system ships versioned artefacts with tests and evidence, and only the latter can be held to account; the status pattern-adjacent was added specifically because that framing left no honest label for a component resembling a pattern without implementing it.
Deciding which profiles to claim
A short decision procedure, for a team reading Part III for the first time.
Start from zero claims: an empty methodProfiles array is a conforming declaration, and clause 4.3 says a consumer may not treat the absence of a claim as a defect.
Then take each profile in turn and ask whether you can hold all of it, because clause 20.3 permits no partial claim.
| If this is true of your organisation | Then |
|---|---|
| You have a working breakpoint system you intend to keep | Do not claim afds-layout-intrinsic; declare your media-query use in reflowBehaviour (clause 11.1) and you satisfy the core |
You need position: sticky | Do not claim afds-layout-intrinsic; record your own approach and evidence (clause 21.7) |
You have a fixed brand palette and a type scale you did not derive from 1rem | Do not claim afds-typography-colour; the core still requires the contrast assertions and evidence |
| You have wide data tables and want the exception scoped rigorously | afds-reflow-scoped is likely worth claiming; clause 11.2 binds you either way |
| Your component catalogue is larger than the eight gated priorities and you intend to keep it | Do not claim afds-patterns-native-first; clause 24.6 prohibits a catalogue larger than the product needs |
| You like nine tenths of a profile | Adopt the requirements, cite the clauses, record the departure as a product-deviation naming the clause, and do not list the profile (clauses 20.3, 13) |
Having decided, declare what you claim separately from your completeness profile, and let neither be inferred from the other (clauses 4.5, 20.2, 34).