Skip to main content

SITIST - сборник статей про веб разработку

position-anchor — позиционирование от якоря

Итак, сюрприз. Раньше мы могли позиционировать элементы только от ближайшего предка, имеющего position, отличный от static. А теперь можем вообще от любого элемента на странице. Дальше речь пойдет об экспериментальных технологиях, поэтому проверяйте поддержку свойств на caniuse.com

Редакторский черновик CSS Anchor Positioning

position-anchor

Синтаксис


position-anchor: auto | <dashed-ident>;

auto — Связывает позиционируемый элемент с его неявным элементом привязки, если таковой имеется — например, как установлено нестандартным anchor атрибутом HTML.

<dashed-ident> — Имя элемента привязки, с которым связывается позиционируемый элемент, должно начинаться с --.

Применение

Свойство position-anchor связывает абсолютно-позиционируемый элемент с любым элементом на странице. Элемент, относительно которого происходит позиционирование, называется якорем.


.anchor {
  anchor-name: --my-anchor;
}
.label {
  position-anchor: --my-anchor;
}

Этот код только связывает элемент с якорем. Чтобы позиционирование заработало, нужно задать абсолютное (absolute) или фиксированное (fixed) позиционирование для .label


<div class="anchor">Якорь, элемент к которому привязываем</div>
<div class="label">Позиционируемый элемент</div>

.anchor {
  anchor-name: --my-anchor;
}
.label {
  position: absolute;
  position-anchor: --my-anchor;
}

position-area

Свойство position-area объявляет, где размещается позиционируемый элемент относительно якоря. Вот несколько значений, которые оно принимает:


top left
top right
bottom left
bottom right

Это значения относятся к физическим направлениям: верх, низ, лево, право. Также можно использовать логические значения. Они адаптируются к языкам, написанным справа налево или вертикально:


block-start
block-end
inline-start
inline-end

Например, в качестве альтернативы top right мы можем использовать block-start inline-end. А также краткие записи start start, start end, end start и так далее. Первый аргумент всегда относится к оси блока, а второй — к inline.

А также по центру:


top center
bottom center
left center
right center

inner round corner

Можно опустить второй аргумент position-area, чтобы охватить всю сторону якоря, а не только его центр:


top
bottom
left
right

Одиночное значение top это сокращенный эквивалент от top span-all

Ещё один набор аргументов, которые принимает position-area. Они охватывают якорь в одном направлении


span-top
span-bottom
span-left
span-right

inner round corner

See the pen (@Websitio) on CodePen.

Чтобы разместить метку поверх якоря в его центре, нужно задать:


position-area: center center;

position-visibility

Свойство position-visibility используется для определения видимости позиционируемого элемента при различных условиях.

always — (значение по умолчанию) метка остается видимой, даже если якорь, к которому она привязана, не виден.

anchors-visible — При этом значении метка видна только тогда, когда якорь тоже виден.

no-overflow — метка исчезает, как только начинает выходить за пределы видимости.

Прокручивайте блок, пока якорь не пропадет. (Возможно, потребуется открыть песочницу в отдельном окне). Как только якорь полностью скроется за границей блока, метка тоже пропадёт.

See the pen (@Websitio) on CodePen.

Попробуйте применить другие значения. Чтобы увидеть эффект от no-overflow, поменяйте позицию bottom на top. То есть, если position-area: top; и край метки чуть заходит за верх основного блока, то она исчезает.

See the pen (@Websitio) on CodePen.

position-try-fallbacks

А вот это свойство — просто мечта разработчика 🩷

До этого мы рассматривали примеры, в которых метка просто исчезала. Но ведь хочется сделать так, чтобы она оставалась, не обрезалась и меняла положение на какую-то другую сторону.

Свойство position-try-fallbacks может справиться с этим. Оно принимает следующие значения: flip-block, flip-inline, flip-start. Оно также может принимать альтернативные значения position-area.

При прокручивании блока, в тот момент, когда метка перестает помещаться сверху от якоря, она меняет положение на указанное в position-try-fallbacks.

See the pen (@Websitio) on CodePen.

position-try-fallbacks также принимает альтернативные значения position-area, такие как top right и bottom right.

Можно задавать position-try-fallbacks несколько значений, разделенных запятыми, например, position-try-fallbacks: left, right

flip-block, flip-inline обрабатывает переполнения в вертикальном или горизонтальном направлениях. Но это не очень хорошо работает, когда метка переполняется и вертикально, и горизонтально одновременно. Чтобы справиться с этим, можно добавить третье значение, которое объединяет первые два: flip-block flip-inline.

Получается вот что:


position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;

position-try-order

Свойство position-try-order определяет стратегию, используемую для определения того, какой резервный вариант применяется. Значения включают:


normal
most-height
most-width
most-block-size
most-inline-size

По умолчанию резервный вариант активируется, когда метка начинает переполняться. Можно изменить это поведение, чтобы выбрать резервный вариант с самой доступной высотой, например, установив position-try-order на most-height.


.label {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top;
  position-try-fallbacks: bottom;
  position-try-order: most-height;
}

position-try

position-try — это сокращенное свойство, которое объединяет position-try-order и position-try-fallbacks

При этом можно указывать только значения position-try-fallbacks — значение position-try-order необязательно.

Таким образом


position-try: most-width left;

можно сократить до


position-try: left;

@position-try

Чудеса ещё не закончились.

Можно определить своё собственное, пользовательское, положение с помощью @position-try

В него может входить что угодно: дополнительные сдвиги top, left, внешние отступы margin, размеры width, max-width, height...

Пользовательское положение нужно назвать используя то же правило, что и в названии якорей, т.е. начиная с --


.label {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top;
  position-try-fallbacks: --custom-bottom;
}

@position-try --custom-bottom {
  position-area: bottom;
  width: 150px;
  margin: 20px;
}

В результате, когда метка сверху, она будет своей обычной ширины. А когда снизу, то ширина станет 150px.

anchor()


top: anchor(bottom);

Таким образом также можно выравнивать метки по якорям. Установка top: anchor(bottom) для метки выровняет её верхний край с нижним краем якоря.


.anchor {
  anchor-name: --my-anchor;
}

.label {
  position: absolute;
  position-anchor: --my-anchor;
  top: anchor(bottom);
}

Или с центром якоря:


top: anchor(center);

Также в процентах или пикселях:


top: anchor(30%);

Можно использовать и логический значения start и end


left: anchor(start)

Следующие две записи идентичны и установят метку вниз и направо от правого нижнего угла якоря. Разумеется, только при направлении письма слева направо и сверху вниз.


position-area: bottom right;

top: anchor(end);
left: anchor(end);

anchor-center

Хотя anchor(), в сочетании с top и left, обеспечивает более детальный контроль по сравнению с position-area, этот подход не позволяет центрировать элемент по его якорю.

Значение anchor() можно использовать с такими свойствами, как justify-self, align-self и place-self. Вот пример горизонтального центрирования с помощью justify-self: anchor-center


.anchor {
  anchor-name: --my-anchor;
}

.label {
  position: absolute;
  position-anchor: --my-anchor;
  top: anchor(bottom);
  justify-self: anchor-center;
}

anchor-size()

Кроме положения метки можно управлять и её размерами в зависимости от размеров якоря.

Сделаем метку ровно по ширине якоря:


width: anchor-size(width);

Если параметр измерения, в данном случае это ширина, совпадает, то аргумент можно опустить.


width: anchor-size();

Другой вариант использования: установим ширину по высоте.


width: anchor-size(height);

А что ещё?

Сочетание с calc(), min() и max()

А ещё, функции anchor() и anchor-size() можно комбинировать с общими функциями CSS, такими как calc(), min() и max().

Установим ширину метки в два раза больше ширины якоря:


.label {
  position: absolute;
  position-anchor: --my-anchor;
  top: anchor(bottom);
  width: calc(2 * anchor-size(width));
}

Найдём самый нижний из якорей с помощью функции max() и привяжем к нему метку

See the pen (@Websitio) on CodePen.

К одному якорю можно привязать несколько элементов


.anchor {
  anchor-name: --my-anchor;
}

.label-1 {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: right top;
}

.label-2 {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: left top;
}

See the pen (@Websitio) on CodePen.

У одного элемента может быть несколько имен якорей


.anchor {
  anchor-name: --my-anchor-1, --my-anchor-2;
}

Это позволит перецеплять метки (элементы привязки) с помощью JS.

Один элемент можно привязать к двум якорям

Задачка из игры про якоря.


.anchor-1 { anchor-name: --my-anchor-1; }

.anchor-2 { anchor-name: --my-anchor-2; }

.label {
  position: absolute;
  left: anchor(--my-anchor-1 end);
  top: anchor(--my-anchor-1 start);
  right: anchor(--my-anchor-2 start);
  bottom: anchor(--my-anchor-2 end);
}

See the pen (@Websitio) on CodePen.

То есть видим ещё один вариант привязки метки к конкретному якорю, без использования position-anchor:


top: anchor(--a2 bottom)

Помощь в изучении

Создатели таких прекрасных игр как Flexbox Froggy и Grid Garden придумали и игру по якорному позиционированию. Рекомендую.

Anchoreum

Поддержка браузерами

Data on support for the css-anchor-positioning feature across the major browsers from caniuse.com

Вверх