Создание качественных всплывающих подсказок (tooltips) и контекстных меню десятилетиями оставалось досадным пробелом веб-платформы. Чтобы показать простую плашку при наведении курсора на иконку, фронтенд-разработчикам приходилось подключать внешние библиотеки вроде Popper.js или Floating UI.
Библиотеки требовались для расчета геометрии: вычисления координат через getBoundingClientRect(), подписки на скролл и переворота тултипа (flip) у края экрана. Релиз браузера Firefox 157 в сочетании с Popover API, атрибутом interesttarget и стандартом CSS Anchor Positioning знаменует долгожданный сдвиг: верстка тултипов становится полностью нативной.
Налог на всплывающие окна: почему мы тащили мегабайты JS
Помимо веса сторонних библиотек (10–25 КБ на страницу), разработчики постоянно боролись с двумя системными дефектами верстки:
- Проклятие
overflow: hidden: если кнопка находилась внутри контейнера со скрытым переполнением (например, в таблице), подсказка неизбежно обрезалась границей родителя. - Война за
z-index: чтобы подсказка не перекрывалась модальными окнами, в стилях появлялись значения вродеz-index: 999999, превращавшие поддержку CSS в кошмар.
Атрибут interesttarget: декларативное проявление интереса
Первым шагом стандартизации стал Popover API, однако изначально он был рассчитан на клики (popovertarget). Спецификация WHATWG ввела атрибут interesttarget.
Он активирует показ подсказки, когда пользователь проявляет к триггеру «интерес»:
- Наведение курсора (Hover): браузер автоматически задействует задержку (hover intent delay), исключая мерцание тултипа при случайном пролете курсора.
- Клавиатурный фокус (Focus): при навигации клавишей
Tabподсказка открывается сразу, гарантируя доступность (a11y) для скринридеров без JS-обработчиков. - Скрытие: нажатие клавиши
Escapeили увод фокуса закрывает подсказку нативно.
Магия CSS Anchor Positioning и спасительный Top Layer
Спецификация CSS Anchor Positioning заменяет JS-расчеты декларативными правилами стилей. Кнопка объявляется якорем через anchor-name, а всплывающий блок привязывается к нему через position-anchor.
Всплывающий элемент с атрибутом popover="hint" рендерится в системном контейнере Top Layer (Верхний слой). Элементы Top Layer находятся выше любого узла в DOM, что навсегда решает проблему overflow: hidden и конфликты слоев.
Реализация доступного тултипа без единой строчки скриптов
Соберем нативный тултип с автоматическим переворотом при нехватке места сверху:
<!-- HTML: кнопка-якорь и семантический тултип в Top Layer -->
<button
class="save-btn"
interesttarget="save-tooltip"
aria-describedby="save-tooltip"
>
Сохранить проект
</button>
<div id="save-tooltip" popover="hint" class="tooltip-box">
Зафиксировать текущие изменения в удаленном репозитории
</div>
Стилизация на CSS привязывает координаты подсказки к геометрии кнопки и настраивает автоматический переворот вниз:
/* CSS: декларативное позиционирование через якоря */
.save-btn {
anchor-name: --save-button-anchor;
padding: 8px 16px;
background-color: #0284c7;
color: white;
border-radius: 6px;
border: none;
cursor: pointer;
}
.tooltip-box {
position-anchor: --save-button-anchor;
position: fixed;
/* Размещение над кнопкой с выравниванием по центру */
bottom: anchor(top);
left: anchor(center);
transform: translateX(-50%) translateY(-8px);
/* Автоматический разворот вниз, если сверху край экрана */
position-try-fallbacks: flip-block;
/* Оформление подсказки */
background-color: #0f172a;
color: #f8fafc;
padding: 6px 10px;
font-size: 13px;
border-radius: 4px;
border: 1px solid #334155;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.2);
}
Кроссбраузерный статус и стратегия постепенного улучшения
С выходом Firefox 157 поддержка базовых механизмов Top Layer и Popover API во всех ведущих браузерах достигла зрелости:
- Производительность 60 FPS: расчет геометрии выполняется движком композитора браузера вне основного потока, обеспечивая плавный скролл.
- Стратегия для продакшена: для старых версий браузеров используется легковесный Floating UI Polyfill по принципу прогрессивного улучшения.
Веб-платформа окончательно избавилась от необходимости подключать тяжелые JavaScript-библиотеки ради элементарных компонентов интерфейса.
