Привязка к якорю: CSS Anchor Positioning

Anchor Positioning привязывает один элемент к другому средствами CSS: подсказка встаёт над кнопкой, меню раскрывается под ней, а при нехватке места у края окна браузер сам переносит их на другую сторону. Раньше для этого подключали JavaScript-библиотеки вроде Popper или Floating UI, а теперь современные браузеры поддерживают это из коробки.

Как пользоваться

Выберите сцену, затем ячейку в сетке position-area: центральная ячейка изображает якорь, остальные — место блока вокруг него. Перетащите кнопку к краю сцены или выберите её клавишей Tab и двигайте стрелками ← ↑ → ↓: каждое нажатие сдвигает кнопку на 2% размера сцены, а с зажатым Shift — на 10%: под сценой видно, где блок оказался и сработала ли запасная позиция.

По умолчанию блок всегда виден, чтобы вы могли оценить его положение относительно якоря. Включите «Открывать по нажатию (popover)», чтобы проверить открытие по кнопке, закрытие повторным нажатием, кликом вне блока или клавишей Escape внутри сцены. Anchor Positioning управляет расположением блока, а атрибуты popover и popovertarget — его показом без JavaScript. Готовый HTML учитывает выбранный режим.

Измените содержимое и размеры блока: для меню каждый пункт вводится с новой строки. Ширина может определяться содержимым, совпадать с шириной якоря, быть не меньше неё или задаваться в пикселях. Высота 0 в настройках означает автоматическую высоту; при заданной высоте длинное содержимое прокручивается.

Запасные позиции проверяются в порядке «Вариант 1 → Вариант 2 → Вариант 3». Можно выбрать отражение или конкретную сторону. «Якорь в центр» возвращает кнопку в центр сцены; «Сбросить настройки» восстанавливает исходную подсказку. Кнопка «Поделиться» рядом с CSS копирует ссылку с настройками, содержимым и положением якоря. Смена сцены загружает её готовые настройки.

Предпросмотр работает в браузерах с поддержкой Anchor Positioning; в остальных код можно скопировать, но сцена покажет блок без привязки.

Для вашего удобства рекомендую использовать полноэкранный режим.

Сцена
position-area
position-try-fallbacks
0 — по содержимому. При заданной высоте длинный текст прокручивается.
Для меню каждый пункт — с новой строки. Текст попадёт в ссылку на настройки.

Перетащите кнопку к краю или выберите её клавишей Tab и двигайте стрелками ←↑ → ↓ (с Shift — шагом 10%) — при нехватке места блок перейдёт на запасную позицию.

В режиме popover нажмите кнопку на сцене. Закрытие — повторным нажатием, кликом вне блока или Escape внутри сцены.

Готовим предпросмотр…

CSS

.button {
    anchor-name: --button;
}
.tooltip {
    position: absolute;
    inset: auto;
    position-anchor: --button;
    position-area: top;
    position-try-fallbacks: flip-block;
    margin: 8px;

    /* Оформление */
    box-sizing: border-box;
    white-space: pre-wrap;
    padding: 8px 12px;
    border: 1px solid #c9d0dc;
    border-radius: 8px;
    background: #fff;
    color: #182238;
    overflow-wrap: anywhere;
}

HTML

<button type="button" class="button">Кнопка</button>
<div class="tooltip" id="anchor-content">Подсказка к кнопке</div>

Для предпросмотра включите JavaScript. Пример CSS для подсказки над кнопкой:

.button {
    anchor-name: --button;
}
.tooltip {
    position: absolute;
    inset: auto;
    position-anchor: --button;
    position-area: top;
    position-try-fallbacks: flip-block;
    margin: 8px;

    /* Оформление */
    box-sizing: border-box;
    white-space: pre-wrap;
    padding: 8px 12px;
    border: 1px solid #c9d0dc;
    border-radius: 8px;
    background: #fff;
    color: #182238;
    overflow-wrap: anywhere;
}

Якорь и привязанный элемент

Якорь получает имя в свойстве anchor-name; имя начинается с двух дефисов, как у CSS-переменной. Привязанный элемент указывает это имя в position-anchor и должен быть позиционирован абсолютно или фиксированно — тогда position-area размещает его относительно якоря. Класс кнопки при этом может быть любым: привязку задаёт только совпадение имени в anchor-name и position-anchor.

CSS
.button {
    anchor-name: --button; /* имя якоря */
}
.tooltip {
    position: absolute;
    position-anchor: --button; /* то же имя */
    position-area: top;
}

position-area делит пространство вокруг якоря сеткой 3×3. Одно ключевое слово (top, right) — сторона по центру якоря, два (top left) — угол. Ключевые слова с span- растягивают область на соседнюю ячейку: bottom span-right выравнивает меню по левому краю кнопки и даёт ему расти вправо.

Запасные позиции

Свойство position-try-fallbacks перечисляет, куда переставить элемент, если на основной позиции он не помещается в своём блоке. Браузер пробует варианты по порядку и берёт первый подходящий.

  • flip-block — отразить по вертикали: сверху вниз и обратно.
  • flip-inline — отразить по горизонтали: справа налево и обратно.
  • flip-block flip-inline — оба отражения сразу, в противоположный угол.

Вместо готовых отражений можно указать другую область, например position-try-fallbacks: bottom, left, или собственное правило @position-try с поддерживаемыми дескрипторами положения, размера и выравнивания. В инструменте доступны отражения и четыре стороны; собственные правила можно добавить в скопированный CSS.

Функции anchor() и anchor-size()

Когда сетки недостаточно, координаты задают функцией anchor(): top: anchor(bottom) ставит верх элемента на нижний край якоря. Функция anchor-size() берёт размер якоря — width: anchor-size(width) делает выпадающий список ровно по ширине поля.

CSS
.menu {
    position: absolute;
    position-anchor: --button;
    top: anchor(bottom);
    left: anchor(left);
    min-width: anchor-size(width);
}

Вопросы и ответы

Как привязать popover к кнопке?

Так же, как обычный блок: задайте кнопке anchor-name, а элементу с атрибутом popover — position-anchor и position-area. Popover по умолчанию фиксирован и отцентрован стилями браузера, поэтому сбросьте у него inset: auto и задайте свой margin. Открытие и закрытие по кнопке с popovertarget работает без JavaScript.

Почему элемент не привязывается к якорю?

Частые причины: у элемента нет position: absolute или fixed; имя в position-anchor не совпадает с anchor-name; якорь лежит внутри блока с position: relative или transform, а привязанный элемент — снаружи, и такой якорь ему недоступен; якорь идёт в разметке после элемента. Проще всего, когда якорь и элемент — соседи и якорь стоит первым.

Почему не сработала запасная позиция?

Отражение выбирается, только если элемент на новом месте помещается целиком. Если места нет ни на одной позиции, браузер оставляет основную, и элемент выходит за край. Добавьте ещё вариантов или ограничьте размер элемента.

Связанные материалы

Основы позиционирования — в уроке «Позиционирование элементов» и в статье о свойстве position. Отработать position и z-index можно в тренажёре размеров и позиционирования.