Let us return to the running-shoe card and ask an uncomfortable question: how does a screen reader even know there is an add-to-cart button on the page? It does not see pixels and it does not read CSS. So somewhere there must be a representation of the interface that states not how the element looks but what it is.
The browser builds such a representation on its own. Besides the DOM (the tree of elements) and the render tree (the tree for painting), it keeps one more - the accessibility tree. This is a cleaned-up model of the page in which every meaningful element is described not by markup but by meaning: what it is, what it is called, what state it is in, and what it is related to. It is this tree, not the picture, that screen readers, voice control, and other assistive technologies work with.
An element's meaning in this tree is made up of several properties. The role is what it is: a button, a link, a heading, an input, a checkbox. The accessible name is what to say aloud: our button's name is Add to cart. The state is what is going on with it right now: pressed, selected, collapsed, disabled. Relationships tie elements together: this field is labeled by that label, this error belongs to that field. A screen reader literally speaks this quartet: button, Add to cart, disabled.
The name deserves a separate note. It does not come from nowhere - the browser computes it from a fixed order of sources (accessible name computation): first explicit labels such as aria-labelledby and aria-label, then the element's own text, then fallbacks such as the title attribute. The takeaway is single: every interactive element must have a name, and better from visible text than from hidden crutches.
To stop this from being an abstraction, it helps to picture one node of the accessibility tree the way an assistive technology sees it.
A developer's naive model: if everything looks right on screen, then everything is fine. But the accessibility tree lives its own life. A clickable div looks like a button yet in the tree is an unnamed container with no role; an unlabeled cart icon lands there as an empty node; a dynamically inserted error message is visible on screen but never enters the tree, and no one voices it. Picture and meaning have diverged - and the assistive-technology user receives the meaning.
To reason about quality systematically, WCAG (Web Content Accessibility Guidelines) introduces four principles known by the acronym POUR. These are not a set of nitpicks but four questions to ask of any element: can its information be obtained through another channel; can it be operated without a precise mouse movement; are its behavior and errors understandable; is it honestly expressed to the platform.
| POUR principle | Practical question | Example of a problem |
|---|---|---|
| Perceivable | Can the information be obtained through another channel? | An icon with no name, a video with no captions. |
| Operable | Can it be operated without a precise mouse movement? | A menu that cannot be opened from the keyboard. |
| Understandable | Are the behavior, errors, and language understandable? | A form that resets with no explanation. |
| Robust | Is the interface correctly expressed to the platform? | A clickable div with no role and no keyboard. |
WCAG comes in conformance levels - A, AA, and AAA - in increasing strictness. A reasonable engineering target for most commercial projects is WCAG 2.2, Level AA: it covers what genuinely stops people from using the product and is achievable without distorting the design. Level AAA should not be declared mandatory for the whole site: some of its criteria depend on the type of content and context and are not applicable everywhere. The AA bar is not a ceiling but an honest minimum.
A failure of this mechanism always looks the same: everything is fine on screen, but there is a hole in the accessibility tree. An Add to cart button on a div with onclick works for a sighted user, but in the tree it has no button role, no name, no state, and no relationship to the price and availability beside it. The screen reader passes it by, voice control cannot find the target by name, and formally the page looks functional. The conclusion from which the whole next chapter grows: accessibility is not solved on top of finished markup, but by choosing the right elements, which have a role, a name, and a state by default.
button "Add to cart" [ state: disabled=false ]
└ related: describedby -> price, availability