Создание тултипов (подсказок) без использования JavaScript

Тултипы без JS: Забудь про Popper.js и лишние килограммы в бандле

Признайся, сколько раз ты подключал тяжелые библиотеки вроде Tippy.js или Popper.js только для того, чтобы показать маленькую плашку с текстом при наведении? Мы привыкли тащить в проект десятки килобайт JavaScript там, где современные браузеры уже давно справляются сами. Тултипы — это классический пример того, как мы по инерции продолжаем использовать сложные решения для простых задач. Сегодня разберем, как выкинуть костыли и собрать идеальную подсказку, которая не боится overflow: hidden и не требует ни единой строчки скриптов.

Как мы страдали раньше

Старая школа верстки предлагала нам два пути, и оба были с подвохом. Первый — использование псевдоэлементов ::before и ::after в связке с content: attr(data-tooltip). Это выглядело изящно до тех пор, пока кнопка не оказывалась внутри контейнера с обрезанными краями. Тултип просто исчезал в небытие, как только пытался выйти за границы родителя.

Второй путь — вложенные спаны с position: absolute. Чтобы это работало, родителю приходилось задавать position: relative, что напрочь ломало иерархию слоев (z-index). Мы тратили часы, пытаясь высчитать отступы и приручить каскадные слои CSS, чтобы подсказка не перекрывалась соседними элементами. Настоящий кошмар начинался при попытке спозиционировать тултип так, чтобы он не вылетал за границы экрана.

Как делать правильно в 2026 году

На дворе эпоха Anchor Positioning API. Это киллер-фича, которая позволяет «привязать» один элемент к другому, даже если они находятся в абсолютно разных частях DOM-дерева. Теперь тултип может лежать хоть в самом конце <body>, что идеально с точки зрения доступности (A11Y), но при этом он будет следовать за своей кнопкой-якорем как приклеенный.

Для реализации нам понадобятся всего два свойства: anchor-name для триггера и position-anchor для самого тултипа. Это позволяет нам навсегда забыть про проблемы с z-index и переполнением контейнеров. Подробнее о механике работы этого чуда ты можешь почитать в статье про якорное позиционирование в CSS, а здесь мы сразу перейдем к практике.

Готовый сниппет кода

Этот код создает тултип, который автоматически привязывается к кнопке и отображается при наведении или фокусе. Обрати внимание, как чисто выглядит HTML.


<!-- Триггер с уникальным именем якоря -->
<button class="trigger" style="anchor-name: --my-tooltip;">
  Наведи на меня
</button>

<!-- Тултип, который может лежать где угодно -->
<div role="tooltip" class="hint" style="position-anchor: --my-tooltip;">
  Я привязан к кнопке через CSS!
</div>

<style>
  .hint {
    /* Основная магия */
    position: absolute;
    top: anchor(bottom);
    left: anchor(center);
    transform: translateX(-50%) translateY(8px);
    
    /* Стилизация */
    background: #333;
    color: white;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 14px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }

  /* Показываем при наведении на триггер */
  .trigger:hover + .hint,
  .trigger:focus + .hint {
    opacity: 1;
  }
</style>

Частая ошибка новичков

Самый частый косяк — забывать про доступность. Многие делают тултипы только для мышки через :hover. Но как насчет пользователей, которые перемещаются по сайту с помощью клавиатуры? Если твой тултип не открывается по :focus, ты отрезаешь часть аудитории.

Также не забывай про атрибуты aria-describedby. Тултип — это не просто красивая плашка, это информация. Скринридер должен понимать, что текст внутри подсказки относится именно к этой кнопке. Всегда связывай id тултипа с атрибутом триггера, иначе твой крутой CSS-код будет бесполезен для инклюзивного веба. И помни: если текст в тултипе слишком длинный, лучше использовать современные методы переноса, о которых мы писали в статье про text-wrap: balance.

🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!

🚀 Прокачай свой код

Готовые CSS-сниппеты, разбор продвинутых фишек и эксклюзивные материалы — в нашем Telegram-канале.

Подписаться
error: Content is protected !!
Прокрутить вверх