Непоследовательное поведение браузеров при нажатии на кнопки
Я заметил, что браузеры непоследовательны в том, как они обрабатывают щелчок по <button>
. Некоторые браузеры предпочитают фокусироваться на кнопке. Некоторые браузеры этого не делают.
В этой статье я хочу показать вам мой тест и выводы. Затем я хочу поговорить о способе преодоления этих несоответствий.
Тест
Тест простой. Мы проверяем, что происходит, когда мы нажимаем на <button>
. В частности, мы хотим знать, если:
- Нажатие фокусирует кнопку?
- После нажатия кнопки происходят нажатия клавиш?
- После нажатия мы можем перейти к следующему элементу?
- После нажатия мы можем сдвинуть табуляцию к предыдущему элементу?
Вот HTML, который мы используем для теста:
<div tabindex="0">Placeholder for testing tab</div>
<button>Button</button>
<div tabindex="0">Placeholder for testing tab</div>
<div>
s предназначены для того, чтобы мы могли легко протестировать табуляцию и сдвиг табуляции.
Вот Codepen для вас, если вы хотите пройти тесты.
См. перо Проверка фокуса кнопки и ссылки Зелл Лью (@zellwk) на КодПен.
Тестирование на фокус
Мы можем проверить фокусировку визуально. Если кнопка получает фокус, вокруг кнопки должно быть визуальное свечение по умолчанию.
Мы также можем проверить фокус программно. В JavaScript вы можете получить сфокусированный элемент с помощью document.activeElement
. Когда мы нажимаем кнопку, мы можем регистрировать сфокусированный элемент.
const button = document.querySelector('button')
button.addEventListener('click', event => {
console.log('Click:', document.activeElement)
})
Примечание. Если вы используете Chrome, вы можете использовать инструмент Live Expression (поэтому нет необходимости document.activeElement
).
Тестирование нажатия клавиш
Здесь мы можем добавить keydown
прослушиватель событий для документа. Здесь мы хотим зарегистрировать, какой элемент вызвал событие. Мы можем сказать элемент с event.target
.
document.addEventListener('keydown', event => {
console.log(`Keydown:`, event.target)
})
Тестирование для Tab и Shift-Tab
После нажатия на кнопку Tab переходит к следующему фокусируемому элементу? Если он переходит к следующему фокусируемому элементу, этот элемент должен получить контур фокуса.
Точно так же делает Shift
+ Tab
переходит к предыдущему фокусируемому элементу? Если он переходит к предыдущему фокусируемому элементу, этот элемент также должен получить контур фокуса.
я не вошел document.activeElement
потому что свечения фокуса достаточно.
Полученные результаты
Сафари (Мак)
Когда вы нажимаете кнопку в Safari (12.1.1), кнопка не получает фокус. Вместо этого документ получает фокус. Мы знаем это, потому что:
- На кнопке нет свечения фокусировки.
document.activeElement
указывает на<body>
.
С <body>
получает фокус, любое последующее нажатие клавиши происходит из <body>
.
Переход к следующему элементу работает, как и ожидалось. Следующий элемент получает фокус.
Shift
+ Tab
не работает, как я ожидал. Я ожидаю, что предыдущий элемент получит фокус, но <button>
вместо этого получает фокус.
Фаерфокс (Мак)
При нажатии на кнопку в Firefox (Nightly 70.0a1) кнопка не получает фокус. Вместо этого документ получает фокус.
Любое дальнейшее нажатие клавиши исходит из <body>
.
Tab
не работает должным образом. Когда вы нажимаете Tab
Firefox фокусируется на первом элементе документа.
Shift
+ Tab
смешно. Если <button>
это первое, на что вы нажали, Firefox фокусируется на последнем элементе в документе, на котором можно сделать фокус. Если вы сфокусировались на элементе до того, как нажали кнопку, Firefox сфокусирует этот элемент.
Проблема с Firefox и кнопками восходит к Firefox 63 (как минимум). В MDN есть раздел по этому поводу:
Фаерфокс (Windows)
Когда вы нажимаете кнопку в Firefox (Quantum 68.0.1, версия для Windows), кнопка получает фокус, но свечение фокуса не появляется.
Дальнейшее нажатие клавиши происходит от <button>
.
Вкладка работает как положено. Следующий элемент получает фокус.
Shift
+ Tab
работает как положено. Предыдущий элемент получает фокус.
Хром (Мак)
Когда вы нажимаете кнопку в Chrome (Canary 78.0), кнопка получает фокус. Эта реализация отличается от Safari и Firefox.
Следующее нажатие клавиши происходит от <button>
. Это ожидается, поскольку <button>
является сфокусированным элементом.
Tab
работает как положено. Следующий элемент получает фокус.
Shift
+ Tab
работает как положено. Предыдущий элемент получает фокус.
Хром (Windows)
Когда вы нажимаете кнопку в Chrome (Chrome 75.0), кнопка получает фокус.
Следующее нажатие клавиши происходит от <button>
.
Tab
работает как положено. Следующий элемент получает фокус.
Shift
+ Tab
работает как положено. Предыдущий элемент получает фокус.
Край (Windows)
При нажатии на кнопку в Edge (Edge 17) кнопка получает фокус, но кольцо фокусировки не появляется.
Следующее нажатие клавиши происходит от <button>
.
Tab
работает как положено. Следующий элемент получает фокус.
Shift
+ Tab
работает как положено. Предыдущий элемент получает фокус.
Мы проверили четыре вещи в распространенных браузерах:
- Нажатие фокусирует кнопку?
- После нажатия кнопки происходят нажатия клавиш?
- После нажатия мы можем перейти к следующему элементу?
- После нажатия мы можем сдвинуть табуляцию к предыдущему элементу?
Вот результаты в виде таблицы.
Тест | Сафари | Фаерфокс () | Фаерфокс (⊞) | Хром () | Хром (⊞) | Край (⊞) |
---|---|---|---|---|---|---|
Сфокусированный элемент | <body> | <body> | <button> (но без свечения фокуса) | <button> | <button> | <button> (но без свечения фокуса) |
Следующее нажатие клавиши от: | <body> | <body> | <button> | <button> | <button> | <button> |
Вкладка переходит на: | Следующий элемент | Первый элемент в документе | Следующий элемент | Следующий элемент | Следующий элемент | Следующий элемент |
Shift + Tab переходит к: | <button> | Ранее сфокусированный элемент (если есть) | Предыдущий элемент | Предыдущий элемент | Предыдущий элемент | Предыдущий элемент |
Здесь вы можете увидеть несоответствия. Это ясно как божий день. Основными несоответствиями являются:
- Firefox на Mac просто странный. Все кажется неправильным.
- Некоторые браузеры не фокусируются на кнопке когда они нажаты.
- Некоторые браузеры не включают свечение фокуса на кнопку, когда они нажаты.
Спецификация HTML не указывает, что браузеры должны делать после того, как пользователь нажмет кнопку. Так ни один браузер не виноват за непоследовательное поведение.
Вот потенциальное исправление
Я думаю, что реализация Chrome (как для Mac, так и для Windows) имеет наибольший смысл.
- Когда вы нажимаете на кнопку, фокус должен быть на кнопке.
- Кнопка должна иметь свечение фокуса.
- Когда вы нажимаете
Tab
после нажатия кнопки фокус должен получить следующий элемент. - Когда вы нажимаете
Shift
+Tab
после нажатия кнопки предыдущий элемент должен получить фокус.
Примечание. Если вы относитесь к тому типу людей, которые ненавидят стиль фокусировки по умолчанию, вы можете изменить стиль кольца фокусировки (или подождать, пока :focus-visible
получить широкую поддержку).
Есть быстрое решение, если вы хотите, чтобы другие браузеры вели себя согласованно с реализацией Chrome. Все, что вам нужно сделать, это добавить этот код вверху вашего JavaScript.
document.addEventListener('click', event => {
if (event.target.matches('button') {
event.target.focus()
}
})
Этот код фокусируется на кнопке, когда вы нажимаете на нее. Это также гарантирует:
- Появится свечение фокуса.
- Tab переходит к следующему элементу.
- Shift-Tab переходит к предыдущему элементу
Важная заметка: Вы хотите поместить этот код В НАЧАЛО ваших файлов JavaScript. Это работает, потому что прослушиватели событий вызываются в том порядке, в котором они объявлены. Фокус всегда будет сначала идти на кнопку. Затем вы можете перенаправить фокус на другие элементы, если хотите.
Важное примечание №2: Я еще не тестировал этот код полностью на всех устройствах. (Только версии Safari, Firefox и Chrome для Mac). Я ценю это, если вы можете помочь провести некоторые тесты. Дайте мне знать, если я ошибаюсь в любом случае. Спасибо.
Если вам интересно, зачем я проводил эти тесты: я понял непоследовательное поведение, когда писал раздел «Клавиатура» для Изучайте JavaScript. Я провел эти тесты, потому что хотел научить своих учеников правильно обращаться с кнопками и фокусом (что является важной частью доступности!).
Спасибо за чтение. Эта статья изначально была размещена на мой блог. Подписаться на моя рассылка если вы хотите больше статей, которые помогут вам стать лучшим разработчиком внешнего интерфейса.