Клавиша / esc

Гайд по Anchor Positioning

Всё, что нужно знать про Anchor Positioning: основные термины, свойства и функции, полезные ссылки по теме.

Время чтения: 12 мин

Что такое Anchor Positioning?

Скопировано

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

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

И это было жутко неудобно. Требовалось вкладывать один элемент в другой, что не всегда возможно по семантике. А реализация адаптивности на JavaScript была не самой тривиальной задачей и могла негативно влиять на отзывчивость страницы, если это всё неправильно приготовить.

Чтобы решить эту проблему был придуман Anchor Positioing, который позволяет один элемент привязать к другому, как к якорю (anchor — англ. якорь), а также декларативно описать его поведение: в каких местах относительно якоря может располагаться элемент, в какие моменты он должен быть виден или скрыт, а также, как размер элемента зависит от размера якоря.

Технология сейчас в стадии активного развития и внедрения, что-то в ней может меняться. Пожалуйста, обращайтесь к спецификации, если не нашли чего-то в этом гайде.

Основные термины

Скопировано
  • Якорный элемент (якорь / anchor): элемент, к которому должен быть привязан и относительно которого позиционироваться другой элемент.
  • Таргет элемент (таргет / target): элемент, который должен быть привязан к якорю.
Якорный и таргет элементы

Свойства якорного элемента

Скопировано

anchor-name

Скопировано
        
          
          .anchor {  anchor-name: --anchor;}
          .anchor {
  anchor-name: --anchor;
}

        
        
          
        
      

Свойство anchor-name объявляет элемент якорным. Оно задаёт имя, с помощью которого другие элементы могут сослаться на текущий, чтобы спозиционироваться относительно него.

Возможные значения:

  • none — значение по умолчанию, якорное имя не задаётся;
  • <anchor-name> — якорное имя, должно начинаться с двух тире.

Более подробно про свойство anchor-name читайте в отдельной доке.

Свойства, функции и директивы для таргет элемента

Скопировано

position-anchor

Скопировано
        
          
          .target {  position: absolute;  position-anchor: --anchor;}
          .target {
  position: absolute;
  position-anchor: --anchor;
}

        
        
          
        
      

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

Возможные значения position-anchor:

  • auto — значение по умолчанию, дефолтное якорное имя не задаётся;
  • <anchor-name> — имя, заданное в свойстве anchor-name якорного элемента, должно начинаться с двух тире.

Кстати, не забудьте указать для таргет элемента position: absolute или position: fixed, так как Anchor Positioning работает только с данными видами позиционирования.

Более подробно про свойство position-anchor читайте в отдельной доке.

anchor()

Скопировано
        
          
          .target {  top: anchor(bottom);  left: anchor(right);}
          .target {
  top: anchor(bottom);
  left: anchor(right);
}

        
        
          
        
      

Функция anchor() помогает привязать таргет элемент к одной из сторон якорного элемента. Она ссылается на параметры позиционирования якорного элемента и может быть применена только в inset-свойствах.

Открыть демо в новой вкладке

Более подробно про функцию anchor() читайте в отдельной доке.

anchor-center

Скопировано
        
          
          .target {  justify-self: anchor-center;}
          .target {
  justify-self: anchor-center;
}

        
        
          
        
      

anchor-center – новое значение для justify и align-self свойств, при котором таргет элемент центруется относительно якоря по соответствующей оси.

Открыть демо в новой вкладке

anchor-center может быть применимо для свойств:

position-area

Скопировано

Позволяет расположить таргет элемент относительно якоря используя концепцию сетки.

Если обвести бордером границы вьюпорта, а затем провести визуальные линии сверху, снизу, справа и слева относительно якоря, то у нас получится девять ячеек, к которым можно обращаться с помощью ключевых слов top, center, bottom, left, right или с помощью их логических эквивалентов.

Визуализация сетки на основе которой работает свойство position-area.

Лучше понять, какое значение прописать для свойства position-area, чтобы расположить его в нужном месте поможет интерективная демка ниже. В ней можно кликать на любую из ячеек, чтобы выбрать одну ячейку. Также можно зажать и тянуть, чтобы выбрать несколько ячеек.

Открыть демо в новой вкладке

Более подробно про свойство position-area читайте в отдельной доке.

position-try-fallbacks

Скопировано
        
          
          .target {  position-area: top center;  position-try-fallbacks: flip-block;}
          .target {
  position-area: top center;
  position-try-fallbacks: flip-block;
}

        
        
          
        
      

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

Есть несколько вариантов значений и подходов для работы с position-try-fallbacks:

  • none — список альтернативных расположений остается пустым. Значение по умолчанию;
  • <try-tactic> – применяет заранее определенные стратегии альтернативного расположения элемента. Существует три стратегии:
    • flip-block – элемент будет менять свое расположение в блочном направлении;
    • flip-inline – элемент будет менять свое расположение в строчном направлении;
    • flip-start – элемент будет менять ось расположения: если он находился в начале одной оси, то он переместится в начало противоположной оси; если элемент находился в конце одной оси, то он переместится в конец противоположной оси;
  • <position-area> – альтернативное расположение, заданое с помощью значения для свойства position-area;
  • <position-try-option> – имя альтернативного расположения, заданного с помощью директивы @position-try.

Все вышеперечисленные варианты значений (кроме none) можно комбинировать между собой и указывать несколько вариантов через запятую:

        
          
          .target {  position-area: top;  position-try-fallbacks: flip-block, left, right;}
          .target {
  position-area: top;
  position-try-fallbacks: flip-block, left, right;
}

        
        
          
        
      

Попробуйте в демке ниже перетащить якорь к рамзным границам экрана.

Открыть демо в новой вкладке

Более подробно про свойство position-try-fallbacks читайте в отдельной доке.

@position-try

Скопировано
        
          
          @position-try --try-option-name {    property: value;}
          @position-try --try-option-name {
    property: value;
}

        
        
          
        
      

Директива @position-try объединяет набор стилей для альтернативного расположения таргет элемента под именем, которое можно использовать в качестве значения для свойства position-try-fallbacks.

Например, можем для фолбэк-значения добавить отступ и увеличить ширину таргет элемента:

        
          
          .target {  position-area: top;  position-try-fallbacks: --bottom;  width: 300px;}@position-try --bottom {  position-area: bottom;  margin-top: 20px;  width: 600px;}
          .target {
  position-area: top;
  position-try-fallbacks: --bottom;
  width: 300px;
}

@position-try --bottom {
  position-area: bottom;
  margin-top: 20px;
  width: 600px;
}

        
        
          
        
      

Попробуйте в демке ниже переместить якорный элемент сверху-вниз и обратно. Увидите, что в нижней позиции ширина таргета увеличивается и появляется отступ, которого не было в начальной позиции.

Открыть демо в новой вкладке

Более подробно про директиву @position-try читайте в отдельной доке.

position-try-order

Скопировано
        
          
          .target {  position-area: top;  position-try-fallbacks: flip-block, flip-inline;  position-try-order: most-width;}
          .target {
  position-area: top;
  position-try-fallbacks: flip-block, flip-inline;
  position-try-order: most-width;
}

        
        
          
        
      

Свойство position-try-order определяет порядок применения возможных вариантов расположения таргет элемента. Оно указывает на что браузер должен обращать внимание в первую очередь, когда выбирает, какой из фолбэков применить.

Имеет несколько значений:

  • normal – фолбэки будут пробовать примениться в том порядке, в котором они указаны внутри свойства position-try-fallbacks. Значение по умолчанию;
  • most-width – фолбэки начнут применяться, начиная с самого широкого (самой широкой ячейки);
  • most-height – фолбэки начнут применяться, начиная с самого высокого (самой высокой ячейки).

Также для most-width и most-height существуют логические эквиваленты most-block-size и most-inline-size.

Посмотреть на работу свойства position-try-order можно в демке ниже.

Открыть демо в новой вкладке

Более подробно про свойство position-try-order читайте в отдельной доке.

position-try

Скопировано
        
          
          .target {  position-try: most-width flip-inline, bottom;}
          .target {
  position-try: most-width flip-inline, bottom;
}

        
        
          
        
      

Свойство position-try является шорткатом для свойств position-try-order и position-try-fallbacks. Вначале указывается порядок применения (который можно опустить), далее указываются фолбэки через запятую.

Более подробно про свойство position-try читайте в отдельной доке.

position-visibility

Скопировано
        
          
          .target {  position-visibility: anchors-visible;}
          .target {
  position-visibility: anchors-visible;
}

        
        
          
        
      

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

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

Открыть демо в новой вкладке

Свойство position-visibility принимает несколько значений:

  • always – таргет элемент будет виден всегда, пока полностью или частично помещается на экран, видимость таргета не зависит от видимости якоря;
  • no-overflow – таргет элемент будет скрываться, если происходит overflow – таргет элемент не помещается целиком ни в одну из позиций: ни в начальную, ни в фолбэчную;
  • anchors-visible – таргет элемент будет виден, пока виден якорный элемент. Если якорь скрылся, таргет тоже перестанет быть видимым. Является значением по умолчанию.

Более подробно про свойство position-visibility читайте в отдельной доке.

anchor-size()

Скопировано
        
          
          .target {  width: anchor-size(width);}
          .target {
  width: anchor-size(width);
}

        
        
          
        
      

С помощью anchor-size() можно получить значения ширины и высоты якорного элемента. Функция пригодится, если размеры таргет элемента должны зависеть от размеров якоря.

Открыть демо в новой вкладке

Более подробно про функцию anchor-size() читайте в отдельной доке.

Свойства контейнера якорного элемента

Скопировано

anchor-scope

Скопировано
        
          
          .container {  anchor-scope: all;}
          .container {
  anchor-scope: all;
}

        
        
          
        
      

Свойство anchor-scope ограничивает область применения указанных якорных имён поддеревом текущего элемента. За счёт этого можно использовать одно и то же якорное имя на разных элементах, например, в списках.

Открыть демо в новой вкладке

В демке выше три раза используется одно и то же якорное имя: в каждом элементе списка оно повторяется. Без использования anchor-scope все таргет элементы будут ссылаться на последний якорь в DOM-дереве. anchor-scope помогает это всё разрулить, ограничивая область видимости якорного имени поддеревом элемента списка.

Свойство anchor-scope принимает в себя три типа значений:

  • none — ни одно якорное имя не будет ограничено поддеревом текущего элемента. Значение по умолчанию;
  • <anchor-name> — список якорных имен через запятую, видимость которых должна быть ограничена поддеревом текущего элемента. Например, --a, --b;
  • all — все якорные имена в поддереве текущего элемента должны быть доступны только в рамках этого элемента.

Более подробно про свойство anchor-scope читайте в отдельной доке.

Использование нескольких якорей одновременно

Скопировано
        
          
          .anchor-1 {  anchor-name: --anchor-1;}.anchor-2 {  anchor-name: --anchor-2;}.target {  position: absolute;  top: anchor(--anchor-1 bottom);  left: anchor(--anchor-1 right);  right: anchor(--anchor-2 left);  bottom: anchor(--anchor-2 top);}
          .anchor-1 {
  anchor-name: --anchor-1;
}

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

.target {
  position: absolute;
  top: anchor(--anchor-1 bottom);
  left: anchor(--anchor-1 right);
  right: anchor(--anchor-2 left);
  bottom: anchor(--anchor-2 top);
}

        
        
          
        
      

Anchor Positioning позволяет привязывать один и тот же таргет элемент сразу к нескольким якорям одновременно. И это можно очень классно использовать на практике. Например, как в демке ниже, меняя местоположение якорей, мы можем влиять на размер таргет элемента: делать его больше, меньше, или совсем сделать невидимым.

Открыть демо в новой вкладке

Использовать эту механику можно и при реализации UI-компонентов. Например, используя несколько якорей одновременно, можно сверстать тултип, который умеет показываться с каждой из четырёх сторон, при этом его хвостик всегда будет направлен в нужную сторону. Попробуйте в демке ниже перетащить кнопку к разным границам экрана – тултип будет адаптироваться.

Открыть демо в новой вкладке

Кстати, разбор реализации такого тултипа можете найти в нашем рецепте.

Где применять?

Скопировано

Anchor Positioning открывает перед разработчиками очень крутые возможности. То, что раньше было возможно только при помощи JavaScript, теперь можно описать декларативно на CSS. Всё зависит только от полёта вашей фантазии.

Мы немножко поразмышляли, и прикинули, где Anchor Positioning точно может пригодиться.

UI-компоненты

Скопировано

Как мы уже убедились в этом гайде выше, Anchor Positioning может быть полезен при проектировании тултипа. Также можно реализовать и другие компоненты, части которых, должны быть привязаны друг к другу. Например, меню. Попробуйте открыть несколько вложенных уровней меню и проскроллить к разным частям экрана – выпадающие списки смогут адаптироваться.

Открыть демо в новой вкладке

Transition-переходы

Скопировано

Также можно использовать Anchor Positioning для реализации классных transition-переходов. Например, для ховера элементов навигации. Попробуйте навести последовательно на несколько ссылок в демке ниже – задний фон будет перетекать от одного элемента к другому.

Открыть демо в новой вкладке

Визуальные подсказки

Скопировано

Можно реализовать различные визуальные подсказки в интерфейсе. Например, подсказки, указывающие на максимальное и минимальное значения в графике.

Открыть демо в новой вкладке

Графы

Скопировано

На базе Anchor Positioning можно построить граф. Если добавить поверх drag'n'drop, то вершины можно двигать в разные стороны и ничего не будет отваливаться.

Открыть демо в новой вкладке

Анимации

Скопировано

И какой-же фронтенд без крутилок и свистелок? Anchor Positioning можно использовать и для построения классных анимацией.

Открыть демо в новой вкладке

Доступность

Скопировано

Используя Anchor Positioning важно не забывать про доступность. Данное апи позволяет нам только визуально связать элементы друг с другом. Описание семантической связи лежит на плечах разработчика.

Шпаргалка

Скопировано

Чтобы лучше сориентироваться в дальнейшем, какое из CSS-свойств отвечает за какую фичу Anchor Positoining, собрали для вас таблицу-шпаргралку.

Фича CSS-свойство
якорь и таргет anchor-name, position-anchor
местоположение anchor(), position-area, anchor-center
размер anchor-size()
адаптивность местоположения position-try, position-try-fallbacks, position-try-order, @position-try
видимость position-visibility
область применения anchor-scope

Полезные ссылки

Скопировано
  1. Спецификация
  2. Роман Комаров – Future CSS: Anchor Positioning
  3. Anchoreum: игра для изучения Anchor Positioning