---
title: "The accessibility tree of a page"
url: https://recursiveai.org/onehtml/cookbook/accessibility-tree/
description: "Compute the tree a browser exposes to screen readers, with roles, accessible names, levels and hidden state, from HTML and CSS alone, and get the landmark…"
version: "1.0.0"
---

# The accessibility tree of a page

Compute the tree a browser exposes to screen readers, with roles, accessible names, levels and hidden state, from HTML and CSS alone, and get the landmark and heading lists a screen-reader user navigates by.

`AccessibilityTree.Build` takes a document and its cascade. It applies WAI-ARIA 1.2, HTML-AAM, AccName 1.2, Core-AAM and SVG-AAM, and uses Chromium’s choices where the specifications leave room. Each of those choices is listed in [Chromium profile](https://recursiveai.org/onehtml/docs/accessibility-chromium-profile/).

```csharp
using RecursiveAI.OneHtml;
using RecursiveAI.OneHtml.Css;
using RecursiveAI.OneHtml.Accessibility;

Document doc = Document.Parse(File.ReadAllBytes("events.html"));
AccessibilityTree tree = AccessibilityTree.Build(doc, DocumentStyles.Create(doc));

// The tree as an outline: role, name, and the states that are set
void Print(AxNode node, int depth)
{
    if (!node.IsIgnored)
    {
        string name = node.Name.IsEmpty ? "" : $" \"{node.Name.Value}\"";
        string level = node.States.Level is int l ? $" level={l}" : "";
        Console.WriteLine($"{new string(' ', depth * 2)}{node.Role}{name}{level}");
        depth++;
    }
    foreach (AxNode child in node.Children)
    {
        Print(child, depth);
    }
}
Print(tree.Root, 0);

// Why an element is named the way it is, and why one is missing from the tree
Node logo = doc.Root.QuerySelector("a.logo");
AxText logoName = tree.ComputeName(logo);
Console.WriteLine($"Logo link name \"{logoName.Value}\" comes from {logoName.Source}");

Node icon = doc.Root.QuerySelector("button svg");
AxNode? iconNode = tree.Find(icon);
Console.WriteLine($"Icon ignored: {iconNode?.IsIgnored}, hidden: {tree.GetHidden(icon).Reasons}");

// The lists a screen reader offers for jumping around
NavigationLists lists = tree.CreateNavigationLists();
foreach (LandmarkEntry landmark in lists.Landmarks)
{
    Console.WriteLine($"{new string(' ', landmark.Depth * 2)}{landmark.Role} {landmark.Name}".TrimEnd());
}
foreach (HeadingEntry heading in lists.Headings)
{
    Console.WriteLine($"{new string(' ', (heading.Level - 1) * 2)}h{heading.Level} {heading.Name}");
}

// The same tree in Chrome's AX-tree JSON shape
File.WriteAllText("events.ax.json", tree.ToChromeJson());
```

```text
RootWebArea "Events | Harbor Street Library"
  banner
    link "Harbor Street Library"
      image "Harbor Street Library"
    navigation "Main"
      list
        listitem level=1
          link "Books"
            StaticText "Books"
        listitem level=1
          link "Events"
            StaticText "Events"
        listitem level=1
          link "Visit"
            StaticText "Visit"
  main
    heading "Upcoming events" level=1
      StaticText "Upcoming events"
    article
      heading "Story time for ages 3–5" level=2
        StaticText "Story time for ages 3–5"
      paragraph
        StaticText "Saturdays at 10:30 in the children’s room. "
        link "Details"
          StaticText "Details"
      image
    article
      heading "Repair café" level=2
        StaticText "Repair café"
      paragraph
        StaticText "Bring a lamp, a toaster or a torn jacket. Volunteers fix what they can. "
        link "Partner site"
          StaticText "Partner site"
      image "Volunteers at a workbench fixing a lamp"
    form
      textbox "Your email"
      button
  contentinfo
    paragraph
      StaticText "© 2026 Harbor Street Library · "
      link "hello@example.org"
        StaticText "hello@example.org"
  button "Back to top"
    StaticText "Back to top"
Logo link name "Harbor Street Library" comes from Contents
Icon ignored: True, hidden: AriaHidden
banner
  navigation Main
main
  form
contentinfo
h1 Upcoming events
  h2 Story time for ages 3–5
  h2 Repair café
```

What the output shows:

- **Ignored nodes are left out of the outline.** The code skips them but still visits their children, which carry their own status. `IgnoredReasons` on each node says why it was ignored.
- **Names are traced.** `ComputeName` returns the name with its `Source` (`Contents`, `NativeAttribute`, `Placeholder` and others) and the elements it came from (`RelatedElements`). The logo link is named from the `alt` of the image inside it.
- **Hidden content says why.** The submit button’s icon is `aria-hidden`, so it is ignored and the button has no name. That is the `button-name` failure in [Run WCAG checks in CI](https://recursiveai.org/onehtml/cookbook/wcag-checks-ci-sarif/).
- **Landmarks and headings** come from `CreateNavigationLists()`, which also lists links, form fields and tables, each mapped back to its node.

Each `AxNode` also has `States` (checked, expanded, level, required and more), `Relations`, `Focus` and `Diagnostics` (invalid roles, broken ID references, missing required parents). `DomNode` and `SourceBytes` lead back to the markup. `tree.FocusOrder` is the Tab order.

**Without a browser, there is no layout.** Hiding that depends on layout, such as zero size, clipping or off-screen positioning, isn’t known. With a Chrome `DOMSnapshot` you capture yourself and pass as `RenderedFacts`, the tree adds the choices Chromium makes once layout is known (see [Rendered facts](https://recursiveai.org/onehtml/docs/rendered-facts/)).

`ToChromeJson()` writes the tree in the shape of Chrome’s accessibility tree, for comparing with a real browser. How closely it matches is measured in [Chrome AX differential](https://recursiveai.org/onehtml/docs/chrome-ax-differential/). After an edit, `tree.Update(edit, restyle)` recomputes only what the edit reached, and the result equals a full rebuild. For the page as a sequence of announcements, see [Extract visible text](https://recursiveai.org/onehtml/cookbook/extract-visible-text/).

DOM vs accessibility tree, compared with Chrome’s: [The accessibility tree](https://recursiveai.org/onehtml/articles/accessibility-tree/).
