Полное дерево доступности в Chrome DevTools

Йохан Бэй
Johan Bay

Chrome DevTools запускает полное дерево доступности, благодаря чему разработчикам будет проще получить обзор всего дерева. В этом посте вы узнаете, как создается это дерево и как использовать его в своей работе.

Что такое дерево доступности?

Вспомогательные технологии, такие как программы чтения с экрана, используют API специальных возможностей Chromium для взаимодействия с веб-контентом. Базовой моделью этого API является дерево доступности: дерево объектов доступности, к которым вспомогательные технологии могут запрашивать атрибуты и свойства и выполнять действия над ними . Веб-разработчики формируют дерево доступности и манипулируют им в первую очередь с помощью свойств DOM, таких как атрибуты ARIA для HTML .

В Chrome DevTools мы предоставляем панель специальных возможностей, которая помогает разработчикам понять, как их контент подвергается воздействию вспомогательных технологий. Конкретно, когда узел выбран в средстве просмотра дерева DOM, свойства соответствующего узла доступности отображаются на панели вместе с представлением предков узла и его непосредственных дочерних элементов.

Панель специальных возможностей Chrome DevTools.

Как создается дерево?

Прежде чем мы перейдем к тому, как выглядит это новое полное древовидное представление в DevTools, давайте кратко рассмотрим, что такое дерево доступности в более осязаемых терминах. Дерево доступности является производным от дерева DOM. Его структура примерно такая же, но упрощена за счет удаления узлов без семантического содержания, таких как элемент <div> , используемый исключительно для стилизации. Каждый узел в дереве имеет роль, например Button или Heading , и часто имя, которое может быть либо из атрибутов ARIA, либо получено из содержимого узла. Если мы посмотрим на HTML-документ:

<html>
<head>
  <title>How old are you?</title>
</head>
<body>
  <label for="age">Age</label>
  <input id="age" type="number" name="age" value="42">
  <div>
    <button>Back</button>
    <button>Next</button>
  </div>
</body>
</html>

Средство рендеринга в Chromium, называемое Blink, создает внутреннее дерево доступности примерно следующим образом.

role='rootWebArea' focusable name='How old are you?'
  role='genericContainer' ignored
    role='genericContainer' ignored
      role='labelText'
        role='staticText' name='Age'
      role='spinButton' editable focusable name='Age' value='42'
        role='genericContainer' editable
          role='staticText' editable name='42'
      role='genericContainer'
        role='button' focusable name='Back'
          role='staticText' name='Back'
        role='button' focusable name='Next'
          role='staticText' name='Next'

Обратите внимание, что это представление содержит несколько лишних узлов с ролью genericContainer , что, по-видимому, противоречит приведенному выше утверждению о том, что дерево доступности является упрощенной производной от дерева DOM. Тем не менее, большинство этих узлов встречаются только во внутреннем дереве и не будут подвергаться воздействию вспомогательных технологий. Поскольку DevTools собирает информацию о доступности непосредственно из процесса рендеринга, DevTools обрабатывает именно древовидное представление.

Полное дерево доступности в DevTools

Новое дерево полной доступности синхронизировано с деревом DOM, поэтому разработчики могут переключаться между двумя деревьями. Мы надеемся, что новое дерево окажется более доступным для изучения, полезным и простым в использовании.

Теперь, когда вы знаете, как работает дерево доступности, вы можете использовать DevTools, чтобы увидеть, как выглядит новое древовидное представление. Следующий HTML-документ с заголовком, заголовком и двумя кнопками используется для отображения дерева.

<!DOCTYPE html>
<title>Test</title>
<h1>Heading for example page</h1>
<div>
  <button>Back</button>
  <button>Next</button>
</div>

Предыдущее представление дерева позволяло вам исследовать только один узел и его предков.

Предыдущее древовидное представление в DevTools.

Теперь, когда вы переключаете новое дерево, оно заменяет древовидное представление DOM и позволяет вам увидеть полное дерево доступности для страницы:

Новое древовидное представление в DevTools.

Ленивое построение дерева

Чтобы сделать дерево производительным даже для больших сайтов, дерево лениво строится во внешнем интерфейсе по мере его исследования. После расширения узла в дереве дочерние узлы извлекаются через протокол Chrome DevTools (CDP), и дерево перестраивается.

Новое дерево доступности, показывающее результат для большой страницы.

Жить

Новое древовидное представление является активным и динамически обновляется, если дерево доступности изменяется в средстве визуализации. Он подключается к той же механике, которая уведомляет вспомогательные технологии об изменениях в дереве, и использует ее для отправки событий в интерфейс DevTools с обновленными узлами. На практике серверная часть CDP прослушивает обновления дерева, отслеживает, какие узлы были запрошены ранее, и отправляет события во внешний интерфейс DevTools, если какой-либо из этих узлов изменяется.

Сказка о многих деревьях

Из описания того, что такое дерево доступности, вы узнали, как Blink создает дерево доступности для DOM, который он отображает, а DevTools извлекает это дерево через CDP. Хотя это и правда, мы не включили в это описание некоторые сложности. На самом деле существует довольно много разных способов использовать дерево доступности в Chromium. При разработке нового древовидного представления для DevTools мы сделали выбор в отношении того, какую часть внутренних возможностей специальных возможностей Chromium мы хотели бы раскрыть.

Платформы

Каждая платформа имеет свой API специальных возможностей, и хотя форма дерева одинакова на всех платформах, API для взаимодействия с деревом различен, а имена атрибутов могут различаться. DevTools показывает внутреннее дерево Chromium, в котором роли и атрибуты обычно соответствуют тем, которые определены в спецификации ARIA .

Несколько фреймов и изоляция сайта

Поскольку Chromium не только помещает содержимое каждой вкладки в разные процессы рендеринга, но также изолирует межсайтовые документы в разных процессах рендеринга , нам приходится подключаться к каждому внепроцессному дочернему документу отдельно через CDP и получать его дерево доступности. Затем мы сшиваем эти поддеревья вместе во внешнем интерфейсе, чтобы создать иллюзию одного связного дерева, хотя в Chromium они находятся в разных процессах рендеринга.

Игнорируемые и неинтересные узлы

По умолчанию мы скрываем некоторые узлы: игнорируемые узлы и узлы с ролью «generic» без имени. Эти узлы не несут никакого семантического значения и, в случае игнорируемых узлов, не подвергаются воздействию вспомогательных технологий. Мы скрываем эти узлы, чтобы не загромождать древовидное представление. Если бы мы этого не сделали, дерево доступности для большинства веб-страниц выглядело бы примерно так:

Новое древовидное представление со всеми показанными узлами.

Предостережение здесь в том, что по сути это означает, что нам нужно построить еще одно дерево, отличное от того, которое доступно на бэкэнде. Скажем, например, что у нас есть узлы A, B, C и X, где у A есть дочерние элементы X и B, а у X есть дочерние узлы C. Если X игнорируется, мы удаляем X из дерева и вместо этого создаем дерево, в котором С — ребенок А.

Схема, показывающая, как мы обрезаем дерево.

Во внешнем интерфейсе мы строим полное дерево, включая игнорируемые узлы, и обрезаем их только непосредственно перед отрисовкой узлов. Мы делаем это по двум причинам:

  • Это значительно упрощает обработку обновлений узлов из серверной части , поскольку на обеих конечных точках у нас одинаковая древовидная структура. Например, если в этом примере узел B удален, мы получим обновление для узла X (поскольку его дочерние элементы изменились), но если бы мы сократили этот узел, нам было бы сложно выяснить, что обновлять.
  • Это гарантирует, что все узлы DOM имеют соответствующий узел доступности. Когда дерево переключается, мы выбираем узел, соответствующий узлу, выбранному в данный момент в дереве DOM. Итак, в предыдущем примере, если пользователь переключает дерево, когда выбран узел DOM, соответствующий X, мы вводим X между узлами A и B и выбираем X в дереве. Это позволяет пользователю проверить узел доступности для всех узлов DOM и помочь определить, почему узел игнорируется.

Идеи будущего

Запуск нового дерева доступности — это только начало. У нас есть несколько идей для будущих проектов, которые мы могли бы реализовать на основе нового представления, но мы также хотим услышать ваши отзывы !

Альтернативные фильтры

Как объяснялось выше, в настоящее время мы отфильтровываем узлы, которые считаются неинтересными. Мы могли бы предоставить способ отключить это поведение и показать все узлы или предоставить альтернативные фильтры, такие как «Показать узлы ориентиров» или «Показать заголовки» .

Выделите все проблемы

Мы могли бы включить в дерево анализ «лучших практик доступности» и выявить проблемы доступности непосредственно на узлах-нарушителях.

Действия по обеспечению доступности поверхности в DevTools

Дерево, которое мы сейчас показываем, является чисто односторонним: оно позволяет нам получить представление о том, какая информация будет передаваться вспомогательным технологиям при просмотре определенной веб-страницы. Действия по обеспечению доступности представляют собой общение в другом направлении: они позволяют вспомогательным технологиям воздействовать на представленный пользовательский интерфейс. Мы могли бы отображать такие действия в DevTools, чтобы разрешить такие действия, как «щелчок», прокрутка или изменение значений на странице, с помощью API, доступного для вспомогательных технологий.