Библиотека ally.js предоставляет мощные инструменты для управления фокусом и проверки доступности элементов на веб-странице. В ситуациях, когда необходимо перенаправить фокус при ошибках в формах или интерфейсе, она позволяет программно определить, какой элемент должен получить внимание пользователя, и корректно выставить на него фокус.
Фокус может быть перемещён не только по конкретному идентификатору элемента, но и по критериям доступности: видимость, интерактивность, табуляция. Это особенно важно при динамическом контенте, где элементы появляются или скрываются после выполнения действий пользователя.
// Пример базовой установки фокуса на первый интерактивный элемент формы с ошибкой
import ally from 'ally.js';
const formErrors = document.querySelectorAll('.error');
if (formErrors.length > 0) {
ally.query.firstTabbable({ context: formErrors[0] }).focus();
}
В этом примере ally.query.firstTabbable ищет первый интерактивный элемент внутри контейнера с ошибкой, гарантируя, что фокус не попадёт на скрытые или заблокированные элементы.
Для форм, которые создаются или изменяются динамически, обычное
управление фокусом через document.querySelector часто
неэффективно. ally.js обеспечивает реактивный поиск
tabbable-элементов:
const errorContainer = document.getElementById('dynamicFormErrors');
const focusFirstError = () => {
const firstErrorField = ally.query.firstTabbable({ context: errorContainer });
if (firstErrorField) {
firstErrorField.focus();
}
};
errorContainer.addEventListener('DOMNodeInserted', focusFirstError);
Здесь используется событие DOMNodeInserted, чтобы
отслеживать появление новых элементов с ошибками. Когда появляется новый
элемент с классом ошибки, фокус автоматически переносится на первый
tabbable-элемент внутри него.
При сложных формах с множеством полей важно дать пользователю прямой доступ к конкретной ошибке. ally.js позволяет комбинировать фильтры поиска tabbable-элементов с кастомной логикой:
function focusErrorByType(type) {
const errorFields = document.querySelectorAll(`.error[data-type="${type}"]`);
for (let field of errorFields) {
const tabbable = ally.query.firstTabbable({ context: field });
if (tabbable) {
tabbable.focus();
break;
}
}
}
// Перенос фокуса на первое поле с ошибкой типа 'email'
focusErrorByType('email');
Использование фильтрации по data-type обеспечивает
точное управление фокусом, позволяя пользователю быстро исправлять
ошибки без лишнего скроллинга.
Для улучшения пользовательского опыта важно визуально выделять элементы, на которых установлен фокус. ally.js не предоставляет стилизации, но корректно работает с существующими CSS-стилями:
:focus {
outline: 3px solid #ff0000;
outline-offset: 2px;
}
В связке с программной установкой фокуса это позволяет подчеркнуть поле с ошибкой сразу после его активации.
ally.js поддерживает поиск all или first tabbable-элементов и их программное перемещение. Для сложных модальных окон с формами полезно контролировать последовательность фокуса, чтобы пользователь не попадал на элементы вне зоны ошибки:
const modal = document.querySelector('#errorModal');
const tabbableElements = ally.query.tabbable({ context: modal });
if (tabbableElements.length) {
tabbableElements[0].focus(); // фокус на первом интерактивном элементе
}
Можно также использовать ally.focus.next() или
ally.focus.previous() для навигации между элементами формы
по клавише Tab или программно.
При работе с ally.js возможны ситуации, когда элемент недоступен для фокуса (скрыт или заблокирован). Чтобы избежать ошибок в скриптах, рекомендуется проверять результат поиска tabbable-элементов:
const firstTabbable = ally.query.firstTabbable({ context: document });
if (firstTabbable) {
firstTabbable.focus();
} else {
console.warn('Нет доступных элементов для фокуса');
}
Это позволяет безопасно управлять фокусом даже в условиях динамического изменения DOM.
Для полной автоматизации UX при ошибках форм ally.js может быть интегрирован с библиотеками валидации:
import validate from 'some-validation-lib';
const form = document.getElementById('signupForm');
form.addEventListener('submit', (e) => {
e.preventDefault();
const errors = validate(form);
if (errors.length) {
const firstErrorField = ally.query.firstTabbable({ context: errors[0].element });
if (firstErrorField) firstErrorField.focus();
}
});
Фокус автоматически переносится на первое поле с ошибкой после попытки отправки формы, что сокращает время исправления ошибок и повышает доступность интерфейса.
Эти подходы обеспечивают надёжное и предсказуемое управление фокусом при ошибках, повышая удобство работы с формами и интерфейсами для всех пользователей, включая пользователей вспомогательных технологий.