Непоследовательное поведение браузеров при нажатии на кнопки

Я заметил, что браузеры непоследовательны в том, как они обрабатывают щелчок по <button>. Некоторые браузеры предпочитают фокусироваться на кнопке. Некоторые браузеры этого не делают.

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

Тест

Тест простой. Мы проверяем, что происходит, когда мы нажимаем на <button>. В частности, мы хотим знать, если:

  1. Нажатие фокусирует кнопку?
  2. После нажатия кнопки происходят нажатия клавиш?
  3. После нажатия мы можем перейти к следующему элементу?
  4. После нажатия мы можем сдвинуть табуляцию к предыдущему элементу?

Вот 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), кнопка не получает фокус. Вместо этого документ получает фокус. Мы знаем это, потому что:

  1. На кнопке нет свечения фокусировки.
  2. document.activeElement указывает на <body>.
    В Safari документ фокусируется, когда вы нажимаете кнопку

С <body> получает фокус, любое последующее нажатие клавиши происходит из <body>.

Следующее нажатие клавиши происходит из документа.

Переход к следующему элементу работает, как и ожидалось. Следующий элемент получает фокус.

Переход к следующему элементу работает, как и ожидалось.

Shift + Tab не работает, как я ожидал. Я ожидаю, что предыдущий элемент получит фокус, но <button> вместо этого получает фокус.

Вкладка Shift не фокусируется на предыдущем элементе.  Вместо этого он фокусируется на кнопке.

Фаерфокс (Мак)

При нажатии на кнопку в Firefox (Nightly 70.0a1) кнопка не получает фокус. Вместо этого документ получает фокус.

В Firefox документ фокусируется, когда вы нажимаете кнопку

Любое дальнейшее нажатие клавиши исходит из <body>.

Следующее нажатие клавиши происходит из документа.

Tab не работает должным образом. Когда вы нажимаете TabFirefox фокусируется на первом элементе документа.

Tab переходит к первому элементу.

Shift + Tab смешно. Если <button> это первое, на что вы нажали, Firefox фокусируется на последнем элементе в документе, на котором можно сделать фокус. Если вы сфокусировались на элементе до того, как нажали кнопку, Firefox сфокусирует этот элемент.

Поведение Shift-Tab.

Проблема с Firefox и кнопками восходит к Firefox 63 (как минимум). В MDN есть раздел по этому поводу:

Документация MDN относительно нажатия кнопок в Firefox и других браузерах.

Фаерфокс (Windows)

Когда вы нажимаете кнопку в Firefox (Quantum 68.0.1, версия для Windows), кнопка получает фокус, но свечение фокуса не появляется.

Кнопки получают фокус, но свечение фокуса не отображается.

Дальнейшее нажатие клавиши происходит от <button>.

Следующее нажатие клавиши происходит от кнопки.

Вкладка работает как положено. Следующий элемент получает фокус.

Следующий элемент получает фокус.

Shift + Tab работает как положено. Предыдущий элемент получает фокус.

Хром (Мак)

Когда вы нажимаете кнопку в Chrome (Canary 78.0), кнопка получает фокус. Эта реализация отличается от Safari и Firefox.

В Chrome кнопка получает фокус, когда вы нажимаете на нее.

Следующее нажатие клавиши происходит от <button>. Это ожидается, поскольку <button> является сфокусированным элементом.

Следующее нажатие клавиши происходит от кнопки

Tab работает как положено. Следующий элемент получает фокус.

Следующий элемент получает фокус при нажатии на вкладку

Shift + Tab работает как положено. Предыдущий элемент получает фокус.

Предыдущий элемент получает фокус при нажатии Shift + Tab

Хром (Windows)

Когда вы нажимаете кнопку в Chrome (Chrome 75.0), кнопка получает фокус.

Кнопка получает фокус, когда вы нажимаете на нее.

Следующее нажатие клавиши происходит от <button>.

Следующее нажатие клавиши происходит от кнопки

Tab работает как положено. Следующий элемент получает фокус.

Следующий элемент получает фокус при нажатии на вкладку

Shift + Tab работает как положено. Предыдущий элемент получает фокус.

Предыдущий элемент получает фокус при нажатии Shift + Tab

Край (Windows)

При нажатии на кнопку в Edge (Edge 17) кнопка получает фокус, но кольцо фокусировки не появляется.

Кнопка получает фокус при нажатии на нее, но кольцо фокусировки не появляется.

Следующее нажатие клавиши происходит от <button>.

Следующее нажатие клавиши происходит от кнопки

Tab работает как положено. Следующий элемент получает фокус.

Следующий элемент получает фокус при нажатии на вкладку

Shift + Tab работает как положено. Предыдущий элемент получает фокус.

Предыдущий элемент получает фокус при нажатии Shift + Tab

Мы проверили четыре вещи в распространенных браузерах:

  1. Нажатие фокусирует кнопку?
  2. После нажатия кнопки происходят нажатия клавиш?
  3. После нажатия мы можем перейти к следующему элементу?
  4. После нажатия мы можем сдвинуть табуляцию к предыдущему элементу?

Вот результаты в виде таблицы.

ТестСафариФаерфокс ()Фаерфокс (⊞)Хром ()Хром (⊞)Край (⊞)
Сфокусированный элемент<body><body><button> (но без свечения фокуса)<button><button><button> (но без свечения фокуса)
Следующее нажатие клавиши от:<body><body><button><button><button><button>
Вкладка переходит на:Следующий элементПервый элемент в документеСледующий элементСледующий элементСледующий элементСледующий элемент
Shift + Tab переходит к:<button>Ранее сфокусированный элемент (если есть)Предыдущий элементПредыдущий элементПредыдущий элементПредыдущий элемент

Здесь вы можете увидеть несоответствия. Это ясно как божий день. Основными несоответствиями являются:

  1. Firefox на Mac просто странный. Все кажется неправильным.
  2. Некоторые браузеры не фокусируются на кнопке когда они нажаты.
  3. Некоторые браузеры не включают свечение фокуса на кнопку, когда они нажаты.

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

Вот потенциальное исправление

Я думаю, что реализация Chrome (как для Mac, так и для Windows) имеет наибольший смысл.

  1. Когда вы нажимаете на кнопку, фокус должен быть на кнопке.
  2. Кнопка должна иметь свечение фокуса.
  3. Когда вы нажимаете Tab после нажатия кнопки фокус должен получить следующий элемент.
  4. Когда вы нажимаете Shift + Tab после нажатия кнопки предыдущий элемент должен получить фокус.

Примечание. Если вы относитесь к тому типу людей, которые ненавидят стиль фокусировки по умолчанию, вы можете изменить стиль кольца фокусировки (или подождать, пока :focus-visible получить широкую поддержку).

Есть быстрое решение, если вы хотите, чтобы другие браузеры вели себя согласованно с реализацией Chrome. Все, что вам нужно сделать, это добавить этот код вверху вашего JavaScript.

document.addEventListener('click', event => {
  if (event.target.matches('button') {
    event.target.focus()
  }
})

Этот код фокусируется на кнопке, когда вы нажимаете на нее. Это также гарантирует:

  1. Появится свечение фокуса.
  2. Tab переходит к следующему элементу.
  3. Shift-Tab переходит к предыдущему элементу

Важная заметка: Вы хотите поместить этот код В НАЧАЛО ваших файлов JavaScript. Это работает, потому что прослушиватели событий вызываются в том порядке, в котором они объявлены. Фокус всегда будет сначала идти на кнопку. Затем вы можете перенаправить фокус на другие элементы, если хотите.

Важное примечание №2: Я еще не тестировал этот код полностью на всех устройствах. (Только версии Safari, Firefox и Chrome для Mac). Я ценю это, если вы можете помочь провести некоторые тесты. Дайте мне знать, если я ошибаюсь в любом случае. Спасибо.

Если вам интересно, зачем я проводил эти тесты: я понял непоследовательное поведение, когда писал раздел «Клавиатура» для Изучайте JavaScript. Я провел эти тесты, потому что хотел научить своих учеников правильно обращаться с кнопками и фокусом (что является важной частью доступности!).

Спасибо за чтение. Эта статья изначально была размещена на мой блог. Подписаться на моя рассылка если вы хотите больше статей, которые помогут вам стать лучшим разработчиком внешнего интерфейса.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *