Перейти к содержанию

Фокус

Как управлять порядком фокусировки в HTML-документах.

Интерактивные элементы, включая элементы управления формами, ссылки и кнопки, по умолчанию являются фокусируемыми и табулируемыми. Перемещаемые по вкладкам элементы являются частью последовательного порядка навигации по фокусу документа. Другие элементы являются инертными, то есть не интерактивными. С помощью атрибутов HTML можно сделать интерактивные элементы инертными, а инертные - интерактивными.

Из соображений юзабилити всегда следует убедиться, что пользователь знает, какой элемент находится в фокусе. Включите стили CSS :focus, :focus-visible и, как вариант, :focus-within. Это очень важно: стилям фокуса посвящены разделы CSS и Accessibility.

По умолчанию порядок фокуса навигации совпадает с визуальным порядком, то есть с порядком исходного кода. Существуют HTML-атрибуты, которые могут изменять этот порядок, и CSS-свойства, которые могут изменять визуальный порядок содержимого. Изменение порядка табуляции с помощью HTML или порядка визуального отображения с помощью CSS может нанести вред пользовательскому опыту.

Не изменяйте воспринимаемый и реальный порядок табуляции с помощью CSS и HTML. Как видно из следующих двух примеров, порядок вкладок, отличающийся от визуально ожидаемого, сбивает пользователей с толку и ухудшает их восприятие.

В этом примере значение атрибута tabindex сделало порядок вкладок хаотичным:

В данном примере CSS создал расхождение между порядком табуляции и визуальным порядком содержимого:

Объявление flex-flow: row-reverse; изменило визуальный порядок. Кроме того, к шестому слову "This" было применено свойство CSS order, которое визуально переместило это одно слово. Последовательность табуляции - это порядок кода, который больше не соответствует визуальному порядку, что создает неудобства для пользователей клавиатуры.

Функции CSS, включая flexbox, grid, positioning, transforms и multi-column, могут изменять визуальный порядок содержимого. Всегда следите за тем, чтобы содержимое сохраняло логичный порядок табуляции при любом размере области просмотра. Протестируйте содержимое с помощью клавиатуры: Shift + Tab для перемещения назад по содержимому. Всегда следите за тем, чтобы с помощью CSS было видно, какой элемент в данный момент находится в фокусе, и избегайте проблем с доступностью, не изменяя порядок расположения фокусируемых элементов с помощью CSS.

Делаем инертные элементы интерактивными

Атрибуты contenteditable и tabindex, являясь глобальными атрибутами, могут быть добавлены к любому элементу, делая его при этом фокусируемым. Фокусируемые элементы можно также фокусировать с помощью мыши или указателя, установив атрибут autofocus, или с помощью сценария, например, element.focus().

Атрибут tabindex

Глобальный атрибут tabindex, введенный в attributes, позволяет элементам, которые иначе не могли бы получить фокус, получить его, обычно с помощью клавиши Tab, отсюда и название.

Атрибут tabindex принимает в качестве значения целое число. Отрицательное значение делает элемент фокусируемым, но не табулируемым. Значение tabindex, равное 0, делает элемент фокусируемым и табулируемым, добавляя элемент, к которому он применен, в последовательный порядок навигации по фокусу в порядке исходного кода. Значение 1 или больше делает элемент фокусируемым и табулируемым, но добавляет его в приоритетную последовательность табуляции, чего, как мы видели выше, следует избегать.

На этой странице кнопка поделиться, <share-action>, является пользовательским элементом. Параметр tabindex="0" добавляет этот ненормально фокусируемый элемент в порядок табуляции клавиатуры по умолчанию:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<share-action
    authors="@front-end.social/@estellevw"
    data-action="click"
    data-category="web.dev"
    data-icon="share"
    data-label="share, mastodon"
    role="button"
    tabindex="0"
>
    <svg
        aria-label="share"
        role="img"
        xmlns="http://www.w3.org/2000/svg"
    >
        <use href="#shareIcon" />
    </svg>
    <span>Share</span>
</share-action>

Роль role="button" сообщает пользователям программ чтения с экрана, что данный элемент должен вести себя как <button>. При создании пользовательских элементов, имитирующих существующие семантические элементы, включение ARIA-роли является уместным и ожидаемым. Элемент должен предоставлять все возможности реплицируемого элемента. Это можно сделать, расширив копируемый элемент, например, расширив HTMLButtonElement, или добавив tabindex="0" и используя JavaScript для программирования всех функциональных возможностей имитируемого элемента, включая обработку событий указателя и нажатия клавиш Enter и Space. Если бы для кнопки вместо создания пользовательского элемента использовался <button>, то атрибуты tabindex и role были бы не нужны, а события от указателя и клавиатуры обеспечивал бы браузер.

На этой странице есть еще один пользовательский элемент: в локальной навигации есть пользовательский элемент с отрицательным значением tabindex:

1
2
3
4
<web-navigation-drawer
    type="standard"
    tabindex="-1"
></web-navigation-drawer>

Атрибут tabindex с отрицательным значением делает элемент фокусируемым, но не табулируемым. Элемент способен получать фокус, например, через HTMLElement.focus(), но он не является частью последовательного порядка навигации фокуса. Для неперемещаемых элементов с фокусом принято использовать tabindex="-1". Обратите внимание, что если добавить tabindex="-1" к интерактивному элементу, то он перестанет быть доступным для табуляции.

Метод element.focus() может быть использован для установки фокуса на фокусируемые элементы. Обратите внимание, что браузеры прокручивают сфокусированные элементы в поле зрения. По этой причине следует избегать использования element.focus({preventScroll:true}), так как фокусировка на невидимом элементе будет вызывать неприятные ощущения у пользователя.

Если вы хотите запросить документ, чтобы узнать, какой элемент в данный момент находится в фокусе, используйте свойство Document.activeElement, доступное только для чтения.

Элементы с tabindex, равным 1 или более, включаются в отдельную последовательность вкладок. Как можно заметить в Codepen, табуляция начинается с отдельной последовательности, в порядке от наименьшего значения к наибольшему, а затем переходит к элементам в обычной последовательности (без установленного tabindex или tabindex="0") в исходном порядке:

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

Атрибут contenteditable

Атрибут contenteditable был рассмотрен ранее. Установка атрибута contenteditable="true" для любого элемента делает его редактируемым, фокусируемым и частью порядка вкладок. Поведение фокуса похоже на установку tabindex="0", но не то же самое. Вложенные элементы contenteditable являются фокусируемыми, но не табулируемыми. Чтобы сделать вложенный элемент contenteditable доступным для табуляции, добавьте tabindex="0", что добавит его в последовательный порядок навигации с фокусом.

Придание фокуса интерактивным элементам

Атрибут autofocus

Хотя атрибут boolean autofocus является глобальным и может быть установлен для любого элемента, он не делает инертный элемент интерактивным. При загрузке страницы фокус получит первый фокусируемый элемент с установленным атрибутом autofocus, если только этот элемент отображается и не вложен в <dialog>.

Автоматическая установка фокуса на содержимое может запутать. Установка autofocus для элемента управления формой означает, что этот элемент будет прокручиваться в поле зрения при загрузке страницы. Все ваши пользователи, включая пользователей программ чтения с экрана и пользователей с маленькими окнами обзора, могут не "увидеть" инструкций к форме, возможно, даже прокручивая мимо обычно видимой метки элемента управления формой. Атрибут autofocus не изменяет порядок последовательной навигации фокуса в документе. Элементы в последовательности, находящиеся перед элементом с автофокусом, просто пропускаются. По этим причинам не рекомендуется включать атрибут autofocus.

Исключением из рекомендации "не использовать autofocus" является включение атрибута autofocus в элементы <dialog>. При открытии диалога браузер автоматически фокусируется на первом интерактивном элементе, находящемся в фокусе внутри <dialog>, поэтому autofocus на элемент не требуется. Если вы хотите быть уверены, что при открытии диалога фокус будет передан конкретному интерактивному элементу внутри диалога, добавьте к нему атрибут autofocus.

1
2
3
4
5
<dialog open>
    <form method="dialog">
        <button type="submit" autofocus>close</button>
    </form>
</dialog>

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

Делаем интерактивные элементы инертными

Существуют также атрибуты HTML, позволяющие исключить интерактивные элементы из последовательности табуляции. Включение отрицательного tabindex к фокусируемым элементам, добавление атрибута disabled к элементам управления поддерживающих форм, а также добавление глобального атрибута inert к контейнеру - все эти атрибуты делают элементы неперемещаемыми. Эти три атрибута НЕ являются взаимозаменяемыми.

Отрицательное значение tabindex

Как мы выяснили выше, атрибут tabindex с отрицательным значением делает элемент фокусируемым, но не табулируемым. Добавление tabindex="0" к элементу, фокусируемому по умолчанию, включая ссылки, кнопки, элементы управления формами и элементы, которые являются contenteditable, не является необходимым; включение tabindex с отрицательным значением удаляет нормально табулируемые элементы из последовательного порядка навигации фокуса.

Отрицательное значение tabindex не позволяет пользователям клавиатуры фокусироваться на интерактивных элементах, но не отключает элемент. Пользователи указателей по-прежнему могут фокусироваться на элементе. Чтобы отключить элемент, используйте атрибут disabled.

Disabled

Атрибут типа boolean disabled делает элементы управления формы, к которым он применен, и их потомков, если таковые имеются, несфокусированными. Элементы управления отключенной формы не могут быть сфокусированы, не получают событий щелчка мыши и не передаются при отправке формы. Обратите внимание, что disabled не является глобальным атрибутом. Он применяется к <button>, <input>, <optgroup>, <option>, <select>, <textarea>, пользовательским элементам, связанным с формой, и <fieldset>. При установке опции <optgroup> или <fieldset> отключаются все дочерние элементы управления формы, за исключением содержимого первого элемента <fieldset> <legend>.

Те же элементы, которые поддерживают функцию disabled, также являются целевыми для псевдоклассов :disabled и :enabled. Элементы, отключенные с помощью атрибута disabled, обычно стилизуются под светло-серый цвет через таблицу стилей пользовательского агента, даже если установлен accent-color.

Будучи булевым атрибутом, наличие атрибута отключает включенный элемент; его нельзя установить в значение false. Чтобы снова включить отключенный элемент, атрибут должен быть удален, как правило, через Element.removeAttribute('disabled').

Свойство HTMLInputElement.disabled позволяет проверить, отключен ли элемент ввода. Поскольку disabled не является глобальным атрибутом, он не наследуется от HTMLElement, но все поддерживающие его интерфейсы элементов, такие как HTMLSelectElement, HTMLTextareaElement, имеют такое же свойство, доступное только для чтения.

Атрибут disabled не применяется к обычно инертным элементам, которые становятся фокусируемыми с помощью tabindex или contenteditable. Он также не применяется к самому элементу <form>. Для их отключения можно использовать глобальный атрибут inert.

Атрибут inert

При добавлении к элементу глобального булевого атрибута inert этот элемент и все вложенное в него содержимое становятся неактивными - ни кликабельными, ни табулируемыми - и удаляются из дерева доступности. Хотя атрибут inert может быть применен к любому элементу, обычно он используется для разделов содержимого, например, вне экрана или скрытого содержимого.

При применении disabled к элементам управления формы браузер предоставляет стилизацию по умолчанию, а также может быть использован псевдокласс :disabled. Атрибут inert не предоставляет никаких визуальных индикаторов и не имеет соответствующего псевдокласса (однако ему соответствует [inert] селектор атрибутов).

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

Убедитесь, что фокус никогда не перемещается на невидимое содержимое. Все, что выводится за пределы экрана и не становится видимым автоматически при фокусировке, должно быть сделано inert. Если содержимое скрыто, но появляется при фокусировке, как, например, ссылка skip to content link на этой странице, ее не нужно делать инертной.

Источник: Focus

Комментарии