Веб-страницы нередко содержат встроенные документы, загружаемые через
элементы iframe или frame. Такие структуры
позволяют изолировать контент, загружать сторонние виджеты, рекламные
блоки, инструменты аналитики или целые приложения. С точки зрения
доступности подобная архитектура усложняет анализ, поскольку каждый
фрейм представляет отдельный документ со своим DOM-деревом, стилями и
сценариями.
Библиотека axe-core рассматривает каждый документ внутри фрейма как независимую область проверки. При запуске аудита происходит рекурсивное сканирование, которое проходит по основному DOM и затем последовательно анализирует содержимое доступных вложенных фреймов. Такой механизм позволяет выявлять нарушения доступности не только на верхнем уровне страницы, но и внутри встроенных документов.
Механизм анализа фреймов строится вокруг нескольких ключевых этапов:
iframe и
frame в DOM текущего документа.contentDocument.Алгоритм можно представить следующим образом:
Основной документ
├─ iframe #1
│ ├─ DOM iframe #1
│ └─ вложенные iframe
├─ iframe #2
│ └─ DOM iframe #2
└─ основной DOM
Каждый обнаруженный документ проходит тот же набор правил доступности, что и основной.
Главным препятствием при анализе вложенных документов становится политика одного источника (Same-Origin Policy). Браузер запрещает доступ к содержимому фрейма, если его источник отличается от источника текущего документа.
Пример ситуации:
Основная страница: https://example.com
iframe: https://thirdparty.com/widget
В таком случае JavaScript не сможет получить доступ к
contentDocument фрейма. Следовательно, axe-core не
сможет выполнить анализ DOM внутри этого документа.
В отчетах такие фреймы обозначаются как недоступные для проверки.
Если основной документ и фрейм принадлежат одному домену, анализ выполняется автоматически.
Пример страницы:
<iframe src="/components/menu.html"></iframe>
Содержимое menu.html загружается с того же домена,
поэтому axe-core сможет получить доступ к его DOM и выполнить
проверку.
Типичный запуск проверки:
axe.run().then(function(results) {
console.log(results);
});
Внутренний механизм axe-core автоматически найдет доступные фреймы и включит их в анализ.
Фреймы могут содержать другие фреймы. Axe-core обрабатывает их рекурсивно, пока:
Пример структуры:
<iframe src="layout.html"></iframe>
layout.html:
<iframe src="navigation.html"></iframe>
<iframe src="content.html"></iframe>
Алгоритм анализа:
layout.html.navigation.html.content.html.Все найденные нарушения объединяются в один отчет.
Каждое нарушение в отчете содержит путь к элементу DOM. Если проблема обнаружена внутри фрейма, путь включает информацию о фрейме.
Пример фрагмента результата:
{
"id": "image-alt",
"nodes": [
{
"target": [
"iframe#content",
"img.logo"
]
}
]
}
Это означает:
alt находится внутри фрейма
#content.Такая структура позволяет точно определить местоположение проблемы.
Иногда возникает необходимость проверить только конкретный фрейм, а
не всю страницу. Это выполняется через передачу контекста в
axe.run.
Пример:
const frame = document.querySelector("iframe");
axe.run(frame.contentDocument).then(results => {
console.log(results);
});
В этом случае анализируется только DOM указанного документа.
Подобный подход используется при:
Другой подход заключается в запуске axe-core непосредственно внутри фрейма. Это применяется, если скрипт не имеет доступа к родительскому документу или требуется автономный анализ.
Внутри документа фрейма подключается библиотека:
<script src="axe.min.js"></script>
<script>
axe.run().then(results => {
console.log(results);
});
</script>
Каждый фрейм формирует собственный отчет, который затем может быть
отправлен в родительское приложение через postMessage.
При невозможности прямого доступа из-за политики безопасности используется механизм междокументного обмена сообщениями.
Пример передачи результатов:
axe.run().then(results => {
window.parent.postMessage({
type: "axeResults",
payload: results
}, "*");
});
В родительском документе:
window.addEventListener("message", event => {
if (event.data.type === "axeResults") {
console.log(event.data.payload);
}
});
Такая архитектура позволяет объединять результаты анализа даже при разных источниках.
Иногда требуется применять разные наборы правил для разных частей страницы. Axe-core поддерживает передачу конфигурации при запуске.
Пример:
axe.run(frame.contentDocument, {
rules: {
"color-contrast": { enabled: false }
}
}).then(results => {
console.log(results);
});
В данном случае правило проверки контрастности отключается только для указанного фрейма.
Фреймы часто загружаются динамически. Если анализ запускается слишком рано, содержимое документа может быть еще не готово.
Типичная ошибка:
axe.run();
запускается до завершения загрузки iframe.
Правильный подход — ожидание события load.
const frame = document.querySelector("iframe");
frame.addEventListener("load", () => {
axe.run(frame.contentDocument).then(results => {
console.log(results);
});
});
Это гарантирует, что DOM внутри фрейма уже сформирован.
При использовании инструментов автоматизированного тестирования (например, интеграционных тестов) анализ вложенных фреймов выполняется через доступ к их документам.
Пример с использованием браузерного тестового окружения:
cy.get("iframe").then($iframe => {
const doc = $iframe[0].contentDocument;
axe.run(doc).then(results => {
expect(results.violations.length).to.equal(0);
});
});
Подобная схема позволяет включать проверку доступности вложенных компонентов в CI-процессы.
Современные веб-приложения нередко строятся из независимых модулей,
каждый из которых может быть загружен через iframe. В таких
системах важно проверять доступность каждого модуля отдельно.
Практика включает:
Такая стратегия предотвращает ситуации, когда сторонний модуль нарушает требования доступности.
Анализ вложенных документов часто выявляет следующие нарушения:
Отсутствие альтернативного текста
<img src="banner.png">
Неправильная структура заголовков
<h3>Раздел</h3>
<h1>Подраздел</h1>
Недоступные элементы управления
<div oncl ick="submit()">Отправить</div>
Недостаточный цветовой контраст
Эти проблемы могут оставаться незамеченными, если аудит ограничивается только основным документом.
При большом количестве фреймов рекурсивная проверка может влиять на производительность. Axe-core выполняет оптимизацию:
Это обеспечивает баланс между полнотой анализа и скоростью выполнения.
В сложных проектах используется многоуровневая стратегия:
1. Проверка каждого компонента отдельно
Каждый модуль проходит аудит до интеграции.
2. Проверка страницы целиком
Axe-core анализирует основной документ и доступные фреймы.
3. Проверка сторонних интеграций
Если фрейм загружается с другого источника, выполняется отдельный аудит поставщиком компонента.
Такая схема обеспечивает максимальное покрытие проверок доступности.
При отсутствии результатов внутри фреймов обычно проверяются следующие факторы:
contentDocument;Правильная последовательность загрузки и анализа играет ключевую роль в корректности аудита.
В современных интерфейсах значительная часть функциональности может находиться внутри фреймов: формы оплаты, авторизация, редакторы контента, виджеты аналитики. Отсутствие анализа этих областей приводит к неполному аудиту доступности.
Использование рекурсивного анализа axe-core, настройка доступа к документам и организация обмена результатами позволяют обеспечить полноценную проверку даже в сложных многоуровневых структурах веб-страниц.