Пользователи ожидают увидеть дополнительную информацию, не меняя контекст. Подсказки могут быть полезны, когда пользователю нужна дополнительная информация, например определение термина, пояснение к кнопке, на которой есть только значок, или указания по заполнению поля формы.
Создание подсказки
Вы можете создать всплывающее окно с нужным поведением, добавив атрибут popover="hint" к <div> или другому семантически подходящему элементу. Когда пользователь открывает подсказку, другие подсказки popover="hint" скрываются, но подсказки auto и manual остаются видимыми. Она также обрабатывает закрытие вложенных подсказок.
Он также обеспечивает поведение легкого отклонения, поэтому, когда пользователь щелкает или иным образом фокусируется за пределами всплывающего окна, всплывающее окно закрывается.
Элемент подсказки должен иметь атрибут id с уникальным значением:
<!-- MANDATORY: The tooltip container `<div>` must have a `popover` attribute.
the value of `"hint"` ensures it can be "light dismissed". -->
<div popover="hint" id="tooltip">Tooltip content</div>
Пользователь наводит указатель мыши на элемент <a> или <button> или переходит к нему. У элемента должен быть атрибут interestfor, соответствующий атрибуту id подсказки.
<!-- The `interestfor` attribute can be applied to a `<button>` element: -->
<button interestfor="tooltip">Tooltip trigger</button>
<!-- The `interestfor` attribute can also be applied to an `<a>` element: -->
<a interestfor="tooltip" href="">Tooltip trigger</a>
Триггер должен иметь визуальный индикатор, указывающий на то, что при взаимодействии с триггером доступна дополнительная информация.
Специальные возможности в interestfor
При использовании interestfor браузер сам настраивает специальные возможности:
- Неявная семантика. Цель с атрибутом
popover="hint"получает неявную минимальную рольtooltip. НЕ задавайте значениеrole="tooltip"самостоятельно. - Неявная связь. Браузер неявно связывает исходный элемент с целевым с помощью
aria-describedby, если целевой элемент является простым текстом, или с помощьюaria-details, если целевой элемент содержит интерактивный контент. НЕ добавляйте в триггерaria-describedbyилиaria-details. - Интерактивный контент. Поскольку связь при необходимости переключается на
aria-details, целевой элемент может содержать интерактивный контент (например, ссылку внутри карточки интересов).
Ограничения специальных возможностей (WCAG 1.4.13)
Даже если interestfor обрабатывает семантику, описанную выше, ваша реализация ДОЛЖНА соответствовать WCAG 1.4.13 (контент при наведении или фокусе):
- Возможность закрытия. Пользователи должны иметь возможность закрыть подсказку, не перемещая указатель или фокус клавиатуры (например, нажав клавишу
Escape). Нативный атрибутpopoverуправляет этой привязкой автоматически. - Наведение. Указатель должен иметь возможность перемещаться по содержимому подсказки, не закрывая ее. Это позволяет пользователям, которые используют инструменты увеличения, без проблем читать текст подсказки.
- Постоянство. Подсказка должна оставаться видимой, пока не будет убран триггер наведения или фокуса, пользователь явно не закроет ее или ее содержимое не станет недействительным.
Позиционирование подсказки
Подсказка позиционируется с помощью CSS Anchor Positioning. Когда подсказка открывается с помощью interestfor, элемент триггера автоматически становится неявным якорем для всплывающего окна.
В современных браузерах, поддерживающих нативное позиционирование привязки, вам не нужно определять anchor-name для триггера или position-anchor для подсказки. Вы можете разместить подсказку непосредственно относительно ее неявного якоря, используя position-area, и обработать переворот при столкновении с помощью position-try-fallbacks:
[popover] {
/* Implicit anchor from interestfor: no anchor-name or position-anchor needed */
position-area: top;
position-try-fallbacks: flip-block;
margin: unset;
}
Резервные стратегии
Резервные варианты и поддержка Interest Invokers в браузерах
Вызывающие объекты интереса должны быть условно заполнены с помощью пакета полизаполнения interestfor из NPM. Рекомендуем использовать полифил в пакете, а не CDN.
ОБЯЗАТЕЛЬНО. Проверьте, поддерживается ли функция, посмотрев свойство interestForElement в HTMLButtonElement.prototype, и загрузите полифил, только если встроенная поддержка отсутствует.
<script type="module">
if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {
// CDN link only used for example, prefer bundling.
await import("https://unpkg.com/interestfor@latest");
}
</script>
Ограничения полифила CSS
При использовании полифила CSS API немного меняется, чтобы компенсировать отсутствие поддержки нативных псевдоклассов и свойств:
- Псевдоклассы. Полифил не может определять настоящие псевдоклассы
:interest-sourceи:interest-target, поэтому вместо них он применяет классы.interest-sourceи.interest-target. ОБЯЗАТЕЛЬНО: объедините их с:is(), чтобы поддерживать как нативные, так и полифильные состояния.
/* Styles to apply when the effect is being previewed */
:is(:interest-source, .interest-source) { /* ... */ }
:is(:interest-target, .interest-target) { /* ... */ }
- Свойства CSS. Для
interest-delay,interest-delay-startиinterest-delay-endполифил требует использования переменных CSS, поскольку он не может считывать пользовательские свойства напрямую во всех браузерах.
/* Adjust the start and end delay for interest invokers */
[interestfor] {
--interest-delay-start: 0.2s;
interest-delay-start: var(--interest-delay-start);
--interest-delay-end: 0.1s;
interest-delay-end: var(--interest-delay-end);
}
Резервные варианты и поддержка Popover в браузерах
Popover API в основном представляет собой прогрессивное улучшение, но его определяющие характеристики – продвижение верхнего слоя, легкое отклонение и вызов popovertarget – не имеют эквивалента только для CSS. Для старых браузеров нужен полифил или резервный вариант, если вы не хотите его использовать.
Полифил. Чтобы обеспечить поддержку атрибута popover в старых браузерах, условно загрузите @oddbird/popover-polyfill. ОБЯЗАТЕЛЬНО. Проверьте наличие свойства popover в HTMLElement.prototype и загрузите полифил, только если встроенная поддержка отсутствует. Не загружайте его без необходимости.
С помощью сборщика или карты импорта:
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
Если вы не используете сборщик, импортируйте из CDN в <script type="module">:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
Ограничение, связанное со стилями. Полифил не может определить настоящий псевдокласс :popover-open, поэтому вместо него применяется класс .\:popover-open. ОБЯЗАТЕЛЬНО. Объедините эти два правила с помощью :is() или :where(), иначе браузеры, не поддерживающие :popover-open, будут игнорировать правило целиком.
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
В качестве альтернативы для устаревшего резервного варианта без полифила используйте position: fixed и вручную рассчитайте координаты с помощью getBoundingClientRect() или используйте позиционирование по умолчанию с помощью inset: auto, если это допустимо для вашего случая.
popover-polyfill не полифиллит поведение подсказки в браузерах, которые поддерживают popover, но не popover="hint". В таких браузерах подсказка, открытая с помощью фокуса, может оставаться открытой, когда открывается вторая подсказка при наведении указателя мыши.
Чтобы обеспечить поддержку браузеров без позиционирования привязки, вы можете использовать полифилл @oddbird/css-anchor-positioning. Вы также можете использовать @supports, чтобы указать резервную позицию.
Если вы используете полифил @oddbird/css-anchor-positioning для поддержки устаревших браузеров, помните, что он не поддерживает неявные привязки или position-area во всплывающих окнах. Явно задайте anchor-name для триггера, position-anchor для всплывающего окна и позиционируйте его с помощью функций вставки anchor() вместо position-area:
<!-- MANDATORY: Conditionally install the anchor positioning polyfill -->
<script type="module">
if (!("anchorName" in document.documentElement.style)) {
await import("https://unpkg.com/@oddbird/css-anchor-positioning");
}
</script>
button[interestfor="tooltip-attrs"] {
/* MANDATORY: Each trigger and popover pair must have a unique anchor name, referenced by `anchor-name` on the trigger and `position-anchor` on the popover. */
anchor-name: --tooltip-attrs;
}
#tooltip-attrs {
position-anchor: --tooltip-attrs;
/* If using the anchor positioning polyfill with a popover, DO use `anchor()` functions, and not `position-area. */
top: anchor(bottom);
left: anchor(right);
margin: unset;
}