Anchor positioning
CSS Anchor Positioning позволяет позиционировать элемент относительно другого элемента (якоря) без JavaScript.
anchor-nameзадаёт якорь,position-anchorпривязывает к нему,anchorвычисляет координаты.
Зачем нужно
Тултипы, дропдауны, поповеры традиционно требуют JavaScript для расчёта позиции. Anchor positioning решает это на уровне CSS: элемент автоматически позиционируется рядом с якорем и подстраивается при скролле, ресайзе и переполнении.
Где используется
- Тултипы и подсказки
- Дропдауны и меню
- Поповеры (
popoverAPI + anchor positioning) - Комментарии/аннотации привязанные к тексту
- Контекстные панели
Предпосылки
- CSS Positioning (
position: absolute/fixed) - Логические свойства — inline/block оси
Базовый синтаксис
1. Определить якорь
.trigger {
anchor-name: --my-anchor;
}
2. Привязать элемент к якорю
.tooltip {
position: fixed; /* или absolute */
position-anchor: --my-anchor;
/* Позиция через position-area */
position-area: top; /* Над якорем */
}
position-area — простое позиционирование
Размещает элемент в одной из 9 зон вокруг якоря:
┌──────────┬──────────┬─���────────┐
│ top left │ top │ top right│
├───���──────┼──────────┼──────────┤
│ left │ (anchor) │ right │
├──────────┼──────────┼──────────┤
│bottom │ bottom │ bottom │
│left │ │ right │
└──────────┴──────────┴──────────┘
/* Тултип сверху */
.tooltip-top {
position: fixed;
position-anchor: --btn;
position-area: top;
}
/* Меню справа */
.menu-right {
position: fixed;
position-anchor: --btn;
position-area: right;
}
/* Дропдаун снизу по левому краю */
.dropdown {
position: fixed;
position-anchor: --trigger;
position-area: bottom left;
}
anchor — точные координаты
Для более точного контроля:
.tooltip {
position: fixed;
position-anchor: --my-anchor;
/* Расположить снизу якоря, выровнять по левому краю */
top: anchor(bottom);
left: anchor(left);
/* Зазор */
margin-top: 8px;
}
/* По центру над якорем */
.tooltip-centered {
position: fixed;
position-anchor: --my-anchor;
bottom: anchor(top);
left: anchor(center);
translate: -50% 0;
margin-bottom: 8px;
}
Значения anchor
.element {
/* Вертикальные */
top: anchor(top); /* Верх якоря */
top: anchor(bottom); /* Низ якоря */
top: anchor(center); /* Центр якоря */
/* Горизонтальные */
left: anchor(left); /* Левый край */
left: anchor(right); /* Правый край */
left: anchor(center); /* Центр */
/* С процентами */
left: anchor(50%); /* 50% ширины якоря */
}
Полный пример: тултип
<button class="btn" popovertarget="tip">Наведи</button>
<div id="tip" class="tooltip" popover>Подсказка</div>
.btn {
anchor-name: --tooltip-anchor;
}
.tooltip {
position: fixed;
position-anchor: --tooltip-anchor;
position-area: top;
margin-bottom: 8px;
background: #333;
color: white;
padding: 8px 12px;
border-radius: 6px;
font-size: 0.875rem;
white-space: nowrap;
/* Стрелка */
&::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
translate: -50% 0;
border: 6px solid transparent;
border-top-color: #333;
}
}
position-try — fallback при переполнении
Если элемент не помещается, попробовать другие позиции:
.tooltip {
position: fixed;
position-anchor: --btn;
position-area: top; /* Предпочитаемая позиция */
/* Если не помещается сверху, попробовать снизу, потом слева */
position-try-fallbacks:
--try-bottom,
--try-left;
}
@position-try --try-bottom {
position-area: bottom;
margin-top: 8px;
margin-bottom: 0;
}
@position-try --try-left {
position-area: left;
margin-right: 8px;
margin-bottom: 0;
}
Встроенные fallback-ы
.tooltip {
position-area: top;
position-try-fallbacks: flip-block; /* Попробовать bottom */
}
.menu {
position-area: bottom right;
position-try-fallbacks: flip-inline; /* Попробовать bottom left */
}
.popover {
position-area: top;
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
}
Дропдаун-меню
<button class="dropdown-trigger">Меню</button>
<nav class="dropdown-menu">
<a href="#">Профиль</a>
<a href="#">Настройки</a>
<a href="#">Выйти</a>
</nav>
.dropdown-trigger {
anchor-name: --dropdown;
}
.dropdown-menu {
position: fixed;
position-anchor: --dropdown;
position-area: bottom span-right;
margin-top: 4px;
position-try-fallbacks: flip-block;
background: white;
border: 1px solid #e0e0e0;
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
padding: 4px;
min-width: anchor-size(width);
display: none;
.dropdown-trigger:focus + & {
display: block;
}
}
.dropdown-menu a {
display: block;
padding: 8px 16px;
text-decoration: none;
color: #333;
border-radius: 4px;
&:hover {
background: #f5f5f5;
}
}
anchor-size — размер якоря
.dropdown-menu {
/* Минимальная ширина = ширина якоря */
min-width: anchor-size(width);
/* Максимальная высота = высота от якоря до низа viewport */
max-height: calc(100vh - anchor(bottom) - 16px);
}
Частые ошибки
- Забыли
position: fixed/absolute— anchor positioning требует позиционированного элемента - Нет
position-anchor— элемент не привязан ни к какому якорю - Якорь не найден —
anchor-nameдолжен быть уникальным на странице - Не добавлены fallback-ы — тултип может вылезти за экран
Практика
- Создать тултип с
position-area: topи стрелкой - Добавить
position-try-fallbacks: flip-blockдля автоматического переворота - Реализовать дропдаун-меню с
anchor-size(width) - Попробовать
anchorдля точного позиционирования - Протестировать fallback при скролле
Связанные темы
- Логические свойства — inline/block в контексте позиционирования