Accessible website examples, checked one mechanism at a time
Four public URLs, four narrow mechanisms, each dated, and the exact View Source or DevTools step that lets you re-run three of them yourself.
The accessible website examples below are four mechanisms. Each one sits on a single public URL and carries the date it was observed. Also, each comes with the one step that makes it visible on that URL. Three of them take under a minute in a browser you already have open. None of them asks you to trust a screenshot.
What can you actually check on somebody else's site?#
One mechanism, on one page, on the day you look at it. That is the whole unit, and nothing larger survives contact with reality. A site is thousands of pages, built by different teams over several years. Therefore any two of those pages can behave differently, and a claim about the site as a whole is not something anybody can check.
Every example here names four things. First, the mechanism itself. Second, the public URL it lives on. Then, the date it was observed. Finally, the step that shows it to you. All four were observed on 8 September 2026. Because these are live third-party pages run by other people, any of them can change after that date without notice. Therefore the sensible move is to check that date against the day you are reading.
| Mechanism | Public URL | Observed | Surface that answers | What you will see |
|---|---|---|---|---|
| USWDS banner panel | Public URLdesignsystem.digital.gov/components/banner/ | Observed8 September 2026 | Surface that answersView Source, then the Elements panel | What you will seeNo aria-hidden on usa-banner__content in the served HTML. The attribute is there once the scripts have run. |
| GOV.UK character count | Public URLdesign-system.service.gov.uk/components/character-count/ | Observed8 September 2026 | Surface that answersPublished component documentation, not confirmed in served markup | What you will seeTwo elements hold one number: the visible counter marked aria-hidden true, and a visually hidden polite live region. Both are created by JavaScript, so neither appears in View Source. |
| NHS.UK hidden urgency prefixes | Public URLnhs.uk/conditions/measles/ | Observed8 September 2026 | Surface that answersView Source | What you will seeUrgent advice: and Immediate action required: sit in the served HTML, each prefix wrapped in a span with role text. |
| Wikipedia width preference | Public URLen.wikipedia.org/wiki/Web_accessibility | Observed8 September 2026 | Surface that answersView Source for the starting class, the Elements panel for the flip | What you will seevector-feature-limited-width-clientpref-1 on the html element. Switch the Appearance width to Wide and the trailing 1 becomes 0. |
In practice this changes what an example is worth. For instance, a screenshot tells you only what one person saw once. In contrast, a named attribute on a named URL tells you what you will find when you look, or it tells you the page has changed since. In addition, a dated observation makes disagreement productive. If you look and find something different, then either the page changed or the original observation was wrong, and both of those are worth knowing.
Still, none of this is a starting checklist. If your job is building an accessible site from a standing start, then start elsewhere. A practical starting point for building accessible sites covers that ground. What follows assumes something already exists and you want to see how other people solved a specific problem inside it.
Where does the First Rule of ARIA live now?#
The rule still holds. However, the document most often quoted for it no longer does the job people assume. "Using ARIA" became a W3C discontinued draft on 24 February 2026, marked informative only, and W3C states that its four rules are "kept for historical purposes". Meanwhile the requirement itself is stated in ARIA in HTML, which reached W3C Recommendation on 11 August 2026.
- Older than both
The First Rule of ARIA itself
Reach for the native HTML element or attribute that already carries the semantics you need, instead of re-purposing an element and adding an ARIA role, state or property. The rule is older than either status change below.
- 24 February 2026
"Using ARIA" becomes a W3C discontinued draft
Marked informative only. W3C states that its four rules are kept for historical purposes.
- 11 August 2026
ARIA in HTML reaches W3C Recommendation
Section 3, Requirements, states that authors must not use the ARIA role and aria-* attributes in a manner that conflicts with the semantics the specification sets out for the element in question.
Section 3, Requirements, puts it directly: "Authors MUST NOT use the ARIA role and aria-* attributes in a manner that conflicts" with the semantics that specification sets out for the element in question.
The First Rule itself is older than either status change. As the discontinued draft stated it, reach for the native HTML element or attribute that already carries the semantics you need, instead of re-purposing an element and adding an ARIA role, state or property. The ARIA Authoring Practices Guide puts the same instinct in one line on its Read Me First page: "No ARIA is better than Bad ARIA".
Therefore the correction here is a matter of provenance, since the advice itself did not change. Attribute the rule to the document that was retired, then attribute the requirement to the Recommendation that states it. If you keep a coding standard citing the older document as current guidance, that citation is the thing to update.
Why does the USWDS banner ship without aria-hidden?#
Because the script owns that attribute, and a hardcoded one becomes permanent hiding the moment the script does not land. The banner component on the U.S. Web Design System ships its collapsible panel with no aria-hidden in the served HTML. Also, the design system tells implementers not to author one. Its own wording, observed on 8 September 2026: "you should not set aria-hidden="true" on usa-banner__content".
This is the First Rule of ARIA arriving from the other direction. That rule discourages reaching for an ARIA attribute when native semantics already carry the meaning, and here the instruction is narrower while pointing the same way. The attribute is runtime state rather than authored markup. Therefore writing it into the HTML freezes a value that was meant to change, and it fails toward hidden rather than toward visible. That failure direction carries the whole argument. A panel that stays open when a script does not run is a nuisance, whereas a panel permanently hidden from assistive technology is a defect that sighted testing will never surface.
To see it, open View Source on that URL, then search for usa-banner__content and note that there is no aria-hidden on it. Next, open the Elements panel on the same page and look again. The attribute is there, added once the scripts have run.
<!-- View Source, designsystem.digital.gov/components/banner/ -->
<!-- Observed 8 September 2026 -->
<div class="usa-banner__content">
<!-- no aria-hidden on this element in the served HTML -->
</div> <!-- Elements panel, same URL, after the scripts have run -->
<!-- Observed 8 September 2026 -->
<div class="usa-banner__content" aria-hidden="true">
<!-- the attribute is added at runtime, not authored -->
</div> That disagreement between the two views is not a glitch. It is the thing worth learning to read.
Why does GOV.UK render the same character count twice?#
Because one number has to reach two groups of people on different timing, and one element cannot do both jobs. On the GOV.UK Design System character count, the counter you can see is marked aria-hidden="true". Meanwhile a second element, visually hidden, carries the same number as a polite live region for screen readers. Two elements hold one number, and each copy is hidden from a different group.
- The counter you can seeMarked aria-hidden="true", so it is shown to the eye and withheld from assistive technology. One number, one audience.
- The visually hidden copyA second element carrying the same number as a polite live region for screen readers. Hidden from the eye, available to assistive technology.
- Debounced on a 1000ms intervalUpdates to the live region are debounced, so somebody typing is not interrupted on every keystroke.
- Gated by the warning thresholdThe second element stays hidden until the count crosses the warning threshold. The criterion a person would look up for a mechanism like this is WCAG 2.2 Success Criterion 4.1.3 Status Messages, which sits at level AA.
The second element has rules of its own. It stays hidden until the count crosses the warning threshold, and its updates are debounced on a 1000ms interval. Consequently somebody typing is not interrupted on every keystroke. The criterion a person would look up for a mechanism like this is WCAG 2.2 Success Criterion 4.1.3 Status Messages, which sits at level AA.
Two details matter for anyone trying to verify this. First, the description above is read from the organisation's own published documentation for the component. It is not confirmed in served markup, and saying which of the two you have is part of the observation. Second, both elements are created by JavaScript, so neither of them appears in View Source at all.
Which surface should you inspect, View Source or the Elements panel?#
Whichever one answers the question you are actually asking, because those are two different questions. View Source shows what the server sent. In contrast, the Elements panel shows the tree as it stands now, after scripts have added, removed and rewritten parts of it.
The two examples above are the same trap from opposite sides. On the USWDS banner, an attribute is absent from the served HTML and present in the live tree. On the GOV.UK character count, two elements exist in the live tree and neither exists in the served HTML. Both were observed on 8 September 2026.
Read it with View Source, usually Ctrl+U or Cmd+Option+U. It shows what the server sent, before any script ran.
3 lines marked: present on this surface and absent from the other.
- aria-hidden is absent from the served HTML and present in the live tree, added once the scripts have run.
- This surface answers
- View Source answers what the server sent, and here it shows that no aria-hidden is authored into usa-banner__content.
- Neither surface answers
- Neither surface tells you what a screen reader actually announces, which is a third question needing a third tool.
| Specimen | URL | Observed | Disagreement |
|---|---|---|---|
| USWDS banner panel | https://designsystem.digital.gov/components/banner/ | 8 September 2026 | aria-hidden is absent from the served HTML and present in the live tree, added once the scripts have run. |
| GOV.UK character count | https://design-system.service.gov.uk/components/character-count/ | 8 September 2026 | Two elements exist in the live tree and neither exists in the served HTML, because JavaScript creates both. This description is read from the organisation’s own published documentation for the component. It is not confirmed in served markup. |
| NHS.UK hidden urgency prefix | https://www.nhs.uk/conditions/measles/ | 8 September 2026 | None. Both surfaces carry the same markup. |
USWDS banner panel
Served markup (View Source)
<!-- View Source, designsystem.digital.gov/components/banner/ --> <!-- Observed 8 September 2026 --> <div class="usa-banner__content"> <!-- no aria-hidden on this element in the served HTML --> </div>
Live tree (Elements panel)
<!-- Elements panel, same URL, after the scripts have run --> <!-- Observed 8 September 2026 --> <div class="usa-banner__content" aria-hidden="true"> <!-- the attribute is added at runtime, not authored --> </div>
GOV.UK character count
Served markup (View Source)
<!-- View Source, design-system.service.gov.uk/components/character-count/ --> <!-- Observed 8 September 2026 --> <!-- Neither counter element is here. Both are created by JavaScript, --> <!-- so neither of them appears in View Source at all. -->
Live tree (Elements panel)
<!-- Elements panel, same URL, after the scripts have run --> <!-- Observed 8 September 2026 --> <!-- The counter you can see, hidden from assistive technology --> <div aria-hidden="true"> <!-- the count --> </div> <!-- A second element, visually hidden, carrying the same number --> <div aria-live="polite"> <!-- the same count, debounced on a 1000ms interval, --> <!-- and hidden until the count crosses the warning threshold --> </div>
NHS.UK hidden urgency prefix
Served markup (View Source)
<!-- nhs.uk/conditions/measles/, observed 8 September 2026 --> <!-- The wrapper makes VoiceOver read the prefix and the heading as one phrase. --> <span role="text"> <span><!-- hidden visually, not from assistive technology -->Urgent advice: </span> <!-- the visible heading text follows here --> </span> <span role="text"> <span><!-- hidden visually, not from assistive technology -->Immediate action required: </span> <!-- the visible heading text follows here --> </span>
Live tree (Elements panel)
<!-- nhs.uk/conditions/measles/, observed 8 September 2026 --> <!-- The wrapper makes VoiceOver read the prefix and the heading as one phrase. --> <span role="text"> <span><!-- hidden visually, not from assistive technology -->Urgent advice: </span> <!-- the visible heading text follows here --> </span> <span role="text"> <span><!-- hidden visually, not from assistive technology -->Immediate action required: </span> <!-- the visible heading text follows here --> </span>
Specimen: USWDS banner panel, observed 8 September 2026. Surface: Served markup, what the server sent, before any script ran. 3 lines on this surface have no counterpart on the other. aria-hidden is absent from the served HTML and present in the live tree, added once the scripts have run. This surface answers: View Source answers what the server sent, and here it shows that no aria-hidden is authored into usa-banner__content. Neither surface answers: Neither surface tells you what a screen reader actually announces, which is a third question needing a third tool.
Therefore the surface you choose decides the answer you get. Yet picking the wrong one produces a confident wrong answer rather than an error, and nothing warns you. Ask what ships, then read View Source, usually Ctrl+U or Cmd+Option+U. Ask what a person or a screen reader meets, then read the Elements panel, usually F12 or Cmd+Option+I. Neither view tells you what a screen reader actually announces, which is a third question needing a third tool.
In particular this matters on your own site. In practice, server-rendered markup and hydrated markup can diverge in ways nobody planned, and checking the wrong surface is how a fix gets signed off that was never in the shipped bytes. It is also why "I checked the markup" is an incomplete sentence. There are two markups, and you have to say which one you read.
How does NHS.UK carry urgency in text rather than colour?#
By putting the signal into words that a screen reader will read, because a coloured box on its own carries nothing to somebody who cannot see the colour. On nhs.uk/conditions/measles/, observed on 8 September 2026, urgent callout headings open with a visually hidden prefix. Two of them appear in the markup: Urgent advice: and Immediate action required: .
<!-- nhs.uk/conditions/measles/, observed 8 September 2026 -->
<!-- The wrapper makes VoiceOver read the prefix and the heading as one phrase. -->
<span role="text">
<span><!-- hidden visually, not from assistive technology -->Urgent advice: </span>
<!-- the visible heading text follows here -->
</span>
<span role="text">
<span><!-- hidden visually, not from assistive technology -->Immediate action required: </span>
<!-- the visible heading text follows here -->
</span> Also, each prefix is wrapped in a <span role="text">. That role is a WebKit-only affordance and it is not in the ARIA specification. The published reason is specific: VoiceOver otherwise splits the prefix and the heading into two phrases, and the wrapper makes them read as one. That makes it a documented exception rather than an oversight. In addition, the prefix is hidden visually and not from assistive technology, which is the distinction the whole mechanism rests on.
Since these prefixes sit in the served HTML, View Source is the surface that answers here. That is the choice the previous section described, made in practice on a live page. Two criteria are the ones a person would look up for this mechanism. WCAG 2.2 SC 1.4.1 Use of Color sits at level A, and so does SC 1.3.1 Info and Relationships.
The organisation's own stated reasoning is short: clearly worded callout headings help people who cannot distinguish callouts by their colour. Notice that the mechanism and the reason are published together, which is what makes this one checkable in both directions.
What happens when you flip Wikipedia's width preference?#
A class on the <html> element changes, and you can watch it happen. Wikipedia's Vector 2022 skin caps article body text at a maximum width. Consequently lines do not run the full width of the window. Also, the cap ships as a user preference rather than as a fixed decision.
Open en.wikipedia.org/wiki/Web_accessibility, observed on 8 September 2026, then read the class attribute on the <html> element. Look for vector-feature-limited-width-clientpref-1. Next, open the Appearance menu and switch the width to Wide. Read that class again, and the trailing 1 has become 0.
Before, the capped column. The article body sits inside a content container with a max-width, so lines do not run the full width of the window.
vector-feature-limited-width-clientpref-1
After, the Appearance menu set to Wide. The same article body runs the full width of the window. One attribute changed, and you can watch it happen.
vector-feature-limited-width-clientpref-0
Wikimedia's own documentation states that "the content on most pages is placed inside a content container with a max-width of 960px". The research basis it cites for holding line length is a range of roughly 40 to 75 characters. However, that range is Wikimedia's citation rather than a measurement of ours, and nothing here establishes an effect on comprehension or retention.
In short, the transferable part is the pattern rather than the number. A preference stored as a class on the root element is findable on any site. Reading one attribute takes about two seconds. Notice that this example needs both surfaces. The starting class is in the served HTML, so View Source answers what ships. Watching the suffix flip is a change to the live tree, so that half needs the Elements panel. One inspection, two surfaces, and the distinction from earlier made concrete.
What does the ARIA error-count figure actually measure?#
Detected errors, by one instrument, on one population, on one date. Across the top 1,000,000 home pages in February 2026, WebAIM's WAVE stand-alone API recorded 59.1 average detected errors on the 82.7% of pages carrying any ARIA beyond landmark roles, and 42.0 average detected errors on the pages carrying none. Also, the API was run against the rendered DOM rather than the served HTML. That 82.7% share is up from 79.4% in 2025.
Show data table
| Item | Average detected errors per page |
|---|---|
| Pages carrying ARIA beyond landmark roles | 59.1 per page |
| Pages carrying none | 42 per page |
The publisher defuses its own headline in the same report: this does not necessarily mean that ARIA introduced these errors, because these pages were also more complex, though pages typically had significantly more errors when more ARIA was present. WebAIM also records that absence of detected errors does not indicate that a page is accessible or conformant.
However, the publisher defuses its own headline in the same report: "This does not necessarily mean that ARIA introduced these errors (these pages were also more complex), but pages typically had significantly more errors when more ARIA was present."
Therefore the sentence that survives is narrow. Pages using ARIA had more detected errors on average, and it does not follow that ARIA caused them.
Two further bounds belong beside that figure. First, this longitudinal series comes from a single publisher. Second, detection is not conformance. WebAIM says so in its own methodology note, which records that every automated tool it knows of, WAVE included, misses conformance failures it cannot detect. Its conclusion is stated plainly: "Absence of detected errors does not indicate that a page is accessible or conformant."
Consequently a number cannot close an accessibility question on its own. What automated checks do cover is a separate question with its own answer. Our walkthrough of accessibility testing sets out how those checks sit beside the ones a person has to run, and the full figures are published at the WebAIM Million.
When not to use these accessible website examples#
Four limits, and each one resolves into a check you can run yourself.
First, a mechanism verified on one URL establishes nothing about the rest of that site. The USWDS banner observation covers that component, on that page, on 8 September 2026, and it says nothing about any other page on the same domain.
Second, a detected-error count is not an accessibility verdict on anybody's site, including yours. WebAIM's own line above is the boundary. Therefore a clean scan is the start of a question rather than the end of one.
Third, the surface you inspect changes the answer you get. Check View Source when the question was about the live tree, and you will get a clear answer to a question you did not ask, with nothing in the output to tell you so.
Fourth, a mechanism copied without the context it was built for can be wrong on your page. In practice, correct markup for a component depends on how many instances of it are present, because a wrapper that groups several of something is the wrong wrapper around exactly one of it. The inspection that settles this is a count: open your page, count the instances of the component, then check whether the markup you copied assumed a different number. Furthermore, that count is a property of your page and not of the component, so the answer can change as your layout does.
Somebody who runs those four checks and finds nothing to fix is finished with these four. If instead the checks surface work you would rather somebody else carried, then two routes match two different situations. One is a pass over a product that already exists, ending in an audit, the fixes, and a re-test. The other is accessibility testing built into how a product gets built, so that the checking happens while the work happens rather than afterwards.