Псевдокласс :focus | CSS
Элементу, получившему фокус, можно задать стиль с помощью псевдокласса :focus [w3.org].
Чем отличаются :active, :focus и :hover
:active, :focus и :hover равнозначны, побеждает тот, что ниже.
.input2:active < background: red; >.input2:focus < background: green; >.input2:hover
:focus для тегов HTML: input, select и textarea
:focus для всех тегов HTML
:focus можно прописать для любого тега HTML, но если это не элемент формы, то нужно указывать атрибут tabindex или contenteditable.
Это тег div. Его содержимое не поменять.
Это тег div
Это тег div. Его содержимое можно менять.
Это тег div
Как снять фокус CSS
- Кликнуть вне элемента.
- Кликнуть по дочернему элементу, который может иметь фокус.
Нажатие и на зелёное поле, и на синее приведёт к смене фона. Клик по синему полю не снимет фокус.
Нажатие только на зелёное поле приведёт к смене фона. Клик по синему полю снимет фокус с родителя, установит фокус на внутреннем div.
Нажатие на зелёное поле приведёт к смене фона. Повторный щелчок снимет фокус.
Управление фокусом и атрибут inert
Множество вспомогательных технологий используют навигацию с клавиатуры для помощи в восприятии и взаимодействии с контентом. Один из способов подобной навигации — клавиша Tab. Возможно, вы знакомы с ним, если используете Tab для быстрого перемещения между полями формы, не дотягиваясь до мышки или трекпада.
Tab будет перемещаться по интерактивным элементам в том порядке, в котором они отображаются в DOM. Вот почему так важно, чтобы порядок исходного кода соответствовал визуальной иерархии вашего дизайна.
Список интерактивных элементов, по которым можно пройтись клавишей Tab:
- Ссылки с заполненным атрибутом href ;
- ;
- и с сопутствующим им ;
- ;
- ;
- и при наличии контролов;
- , в зависимости от того, как он используется;
- любой элемент с overflow: scroll в Firefox;
- любой элемент с атрибутом contenteditable ;
- любой элемент с установленным атрибутом tabindex (о нём чуть позже).
Интерактивный элемент получает состояние фокуса, когда:
- На него переходят с помощью клавиши Tab,
- Он является ссылкой и на него кликают,
- Фокус программно задан с помощью element.focus() в JavaScript.
Фокус похож на ховер, поскольку так мы определяем элемент, с которым хотим провзаимодействовать. Вот почему визуально очевидные стили для фокуса имеют огромное значение.
Фокус следует по домашней странице. Начиная с логотипа, затем к товарам, услугам, вакансиям, блогу, контактам и останавливается на кнопке «Learn more».
Управление фокусом Скопировать ссылку
Управлять фокусом — значит определять, какие элементы могут его получать, а какие нет. Это один из самых сложных аспектов при разработке веб-интерфейсов, но он важен для доступности сайтов и приложений.
Полезные практики управления фокусом Скопировать ссылку
В 99% случаев вам стоит оставить порядок фокуса в покое. Не устану это повторять.
Состояние фокуса будет работать без дополнительных усилий, если вы используете для кнопок, для ссылок, для полей форм и т. д.
В редких случаях вам может понадобиться добавить фокус к элементам, к которым обычно событие focus не применимо. Вот некоторые рекомендации относительно того, как реализовать это доступно и интуитивно понятно для пользователя.
✅ Следует: узнать побольше про атрибут tabindex Скопировать ссылку
tabindex делает элементы фокусируемыми. В качестве значения он принимает число, в зависимости от которого меняется поведение фокуса.
❌ Не следует: устанавливать tabindex=»0″ там, где это не надо Скопировать ссылку
Нет необходимости устанавливать tabindex для интерактивных элементов, которые могут получать фокус с клавиатуры (например, ). Кроме того, вам не нужно прописывать tabindex неинтерактивным элементам, чтобы их могли прочесть вспомогательные устройства (на самом деле, отсутствие роли и доступного имени является ошибкой с точки зрения WCAG). На самом деле, это даже усложняет навигацию для тех, кто использует вспомогательные устройства. У таких пользователей уже есть другие, ожидаемые ими способы чтения контента.
✅ Следует: устанавливать tabindex=»-1″ для фокуса с помощью JavaScript Скопировать ссылку
Атрибут tabindex=»-1″ используется для создания доступных интерактивных виджетов посредством JS. Прописав tabindex=»-1″ , вы сделаете элемент фокусируемым для JS, а также по клику или тапу, но недоступным через клавишу Tab.
❌ Не следует: использовать положительное значение tabindex Скопировать ссылку
Это антипаттерн. Установив положительное значение tabindex , вы переопределите ожидаемый порядок элементов для фокуса через Tab и запутаете пользователя. Сделать так один раз — уже плохо, несколько — полный кошмар. Серьёзно, не надо так.
❌ Не следует: создавать собственный порядок фокусировки Скопировать ссылку
Пройтись по интерактивным элементам можно только в том порядке, в котором они следуют друг за другом. Не следует создавать множество tabindex со значением, которое увеличивается для каждого последующего элемента, в соответствии с вашим представлением о том, как пользователь должен читать ваш сайт. Позвольте DOM сделать это за вас.
Ловушка фокуса Скопировать ссылку
Иногда есть необходимость запретить состояние фокуса. Хороший пример запрета — это ловушка фокуса, которая временно ограничивает событие фокуса у родительского элемента и у его дочерних элементов.
Ловушку фокуса не стоит путать с ловушкой клавиатуры. Ловушки клавиатуры — это ситуации, когда невозможно закрыть виджет или перейти к другому компоненту из-за вложенного цикла плохо прописанной логики.
Практический пример того, как вы могли бы использовать ловушку фокуса — это модальное окно:
Фокус проходит по странице и открывает модальное окно, чтобы продемонстрировать отмену фокуса. Далее фокус двигается в рамках контента модального окна, на кнопку «Play», кнопку «Cancel», кнопку «Purchase» и кнопку закрытия (всё это время фокус на странице заблокирован). После закрытия модального окна он возвращается к исходному положению на странице до его открытия.
Почему это важно? Скопировать ссылку
Удержание фокуса в пределах модального окна помогает понять, что является его контентом, а что нет. Это аналогично тому, как зрячий человек может видеть, как окно всплывает поверх контента сайта или приложения. Это важная информация, если:
- У вас плохое зрение или слепота и вы полагаетесь на скринридер, чтобы узнать об изменениях после взаимодействия со страницей;
- У вас плохое зрение и интерфейс увеличен с помощью экранной лупы, при которой фокусировка за пределами модального окна может сбить с толку и дезориентировать;
- Вы перемещаетесь исключительно с помощью клавиатуры и, в случае закрытия модального окна, можете потеряться на странице при попытке вернуться обратно к нему.
Как это сделать? Скопировать ссылку
Надёжно управлять фокусом — дело сложное. Нужно прибегнуть к JavaScript, чтобы:
- Определить родительский блок для всех фокусируемых элементов на странице;
- Определить границы содержимого ловушки фокуса (например, модального окна), включая первый и последний фокусируемый элемент;
- Убрать как интерактивность, так и видимость всего, что может иметь фокус и находится вне рамок содержимого ловушки фокуса;
- Переместить фокус на содержимое ловушки фокуса;
- Обрабатывать события, сигнализирующие об уходе с выделенной области (сохранение, отмена, нажатие Esc и так далее);
- Выйти из содержимого ловушки фокуса, когда сработает нужное событие;
- Вернуть раннее отменённую интерактивность;
- Переместить фокус обратно на интерактивный элемент, который вызвал ловушку фокуса.
Зачем нам это? Скопировать ссылку
Не стану врать: все эти действия отнимают много времени. Но всё же, управление фокусом и удобный порядок фокусировки являются частью WCAG (руководства по обеспечению доступности веб-контента). Тема достаточна важна, чтобы считать её частью международного правового стандарта о юзабилити.
Видимость Скопировать ссылку
Существует небольшой трюк, с помощью которого можно легко ограничить видимость и интерактивность элемента.
У скринридеров есть режим взаимодействия, который позволяет им проходить по странице или просматривать её с помощью виртуального курсора. А ещё виртуальный курсор позволяет пользователю скринридера обнаруживать неинтерактивные части страницы (заголовки, списки и т. д.). В отличие от использования Tab, виртуальный курсор доступен только пользователям скринридера.
При управлении фокусом может потребоваться ограничить возможность обнаружения содержимого виртуальным курсором. В нашем примере с модальным окном это значит предотвратить случайный выход пользователя за рамки окна при чтении контента.
Видимость может быть заблокирована с помощью правильного применения атрибута aria-hidden=»true» . А вот с интерактивностью есть один тонкий нюанс.
Знакомство с inert Скопировать ссылку
Атрибут inert — глобальный атрибут в HTML, позволяющий легко убирать и восстанавливать видимость интерактивных элементов, а также их возможность получать состояние фокуса. Вот пример:
Save changes?
The changes you have made will be lost if you do not save them.
Я намеренно избегаю использования для модального окна из-за многочисленных проблем с поддержкой.
Атрибут inert задан элементу , следующему сразу после модального окна сохранения изменений. Теперь всё содержимое не может попасть в фокус и по нему нельзя кликнуть.
Фокус ограничен рамками модального окна. Когда мы закрываем его, то убираем inert из . Этот способ управления ловушкой фокуса проще, чем другие методы.
Помните: событие закрытия модального окна может быть вызвано не только нажатием на кнопки внутри нашего модального окна из примера, но и при нажатии на Esc. А ещё некоторые модальные окна могут быть закрыты по клику на оверлей.
Поддержка inert Скопировать ссылку
Все последние версии Edge, Chrome и Opera поддерживают inert , если включены экспериментальные функции веб-платформ. Также скоро появится его поддержка в Firefox! Единственное исключение — Safari, как мобильный, так и десктопный.
Мне бы очень хотелось, чтобы Apple реализовала встроенную поддержку inert . Хоть полифил и существует, но у него серьёзные проблемы с поддержкой скринридерами. Нехорошо!
Вдобавок хочется обратить внимание на пометку в README полифила:
Полифил обойдётся вам дорого с точки зрения производительности, в отличие от нативного inert , т. к. он требует изрядного количества перемещений по DOM.
Перемещение по DOM подразумевает, что JavaScript в полифиле требует высокой вычислительной мощности и, следовательно, в конечном итоге замедлит использование.
Для устройств с низким энергопотреблением, таких как бюджетные Android-смартфоны и устаревшие ноутбуки, а также тех, что выполняют сложные задачи (например, запуск нескольких приложений сразу), это может привести к зависанию или сбоям. Нативная браузерная поддержка делает такие процессы менее затратными в этом плане, так как у браузера есть доступ ко всем частям DOM, в отличие от JS.
Safari Скопировать ссылку
Лично я разочарован тем, что Apple не поддерживает inert . Хотя понимаю, что добавление новых функций в браузер — невероятно сложная и трудная работа. inert кажется функцией, которую Apple стоило бы начать поддерживать гораздо раньше.
macOS и iOS всегда имели хорошую поддержку доступности, а поддержка вспомогательных технологий — важная часть их маркетинговой кампании. Поддержка inert представляется как естественное продолжение миссии Apple ввиду того, что сама эта функция смогла бы облегчить разработку доступных веб-интерфейсов в разы.
К сожалению, Apple держит в тайне, когда появится поддержка этого атрибута. Поэтому поддержка inert — всё ещё открытый вопрос.
Igalia Скопировать ссылку
Igalia — компания, работающая над функциями браузеров. Сейчас они проводят эксперимент, в котором каждый может проголосовать за те возможности браузеров, которые ему хотелось бы видеть. Конечно, моя статья совсем не про это, но вы можете узнать больше в Smashing Magazine.
Одно из предложений Igalia — это добавление поддержки inert в WebKit. Если вы искали возможность принять участие в улучшении доступности веба, но не знали с чего начать, я могу вам её предоставить. 5 $, 10 $, 25 $ — совсем необязательно жертвовать большие суммы, даже маленький вклад ценен.
Итог Скопировать ссылку
Управление фокусом требует некоторых навыков и осторожности, но это того стоит. Атрибут inert значительно облегчит эту задачу.
Такие техники, как inert , являются примером одной из самых сильных сторон веба: способности кодифицировать неожиданное поведение в нечто простое и эффективное.
Что почитать Скопировать ссылку
- Controlling focus with tabindex (A11ycasts, эпизод 4).
- Using the tabindex attribute (The Paciello Group).
- Using JavaScript to trap focus in an element (Хидде де Врис).
Псевдокласс :focus
Псевдокласс :focus определяет стиль для элемента получающего фокус. Например, им может быть текстовое поле формы, в которое устанавливается курсор.
Синтаксис
Значения
HTML5 CSS2.1 IE Cr Op Sa Fx
focus