Как стать автором
Поиск
Написать публикацию
Обновить

CSS Anchor Positioning API

Уровень сложностиСредний
Время на прочтение10 мин
Количество просмотров1.3K

Введение

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

Ссылка на мой блог в телеграм с новыми фичами и лайфхаками во фронтенд.
Ссылка на другие мои статьи.

Приятного прочтения!

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

В качестве закрепления рекомендую пройти данную игру.

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

Предназначение

Данный API был разработан для того, чтобы упростить работу над tooltip'ами, dropdown меню, контекстными меню и прочими элементами UI, которые должны быть привязаны к какому-то определённому объекту, например к кнопке или полю для ввода даты.

Принцип работы

Для базового позиционирования при помощи Anchor Positioning API нам нужно всего лишь 2 элемента: статический (относительно которого происходит размещение) и динамический (тот, который размещают относительно статического).

Для простоты понимания далее статический элемент будем называть якорем, а динамический - позиционируемым элементом.

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

Звучит просто, да? Тогда идём дальше, к вариантам связки одного элемента с другим.

Связка якоря и позиционируемого элемента

Как и в большинстве API во Frontend, данный механизм реализуется при помощи уникального идентификатора.

Всего существует 2 варианта связки:

  1. При помощи CSS свойств

  2. При помощи HTML атрибутов

Рассмотрим оба:

  1. При помощи CSS свойств

    <div class="anchor">Якорь</div>
    <div class="tooltip">Тултип</div>
    
    .anchor {
      anchor-name: --myAnchor;
    }
    .tooltip {
      position: absolute;
      position-anchor: --myAnchor;
      position-area: top left;
    }

    Якорю необходимо указать свойство anchor-name, а позиционируемому элементу position-anchor с общим, так называемым, dashed ident значением. То есть, со значением с префиксом ввиде двух дефисов, также как и у CSS переменных. Также важно учесть, что у позиционируемого элемента обязательно должно присутствовать свойство position: absolute или position: fixed. Для других типов позиционирования такая привязка работать не будет. И, последнее, что необходимо сделать, это указать позицию, где будет размещён элемент относительно якоря при помощи position-area. В данном примере мы используем значение top left, это как раз одно из тех значений, что мы рассматривали на схеме ранее.

  2. При помощи HTML атрибутов

    <div class="anchor" id="myAnchor">Якорь</div>
    <div class="tooltip" anchor="myAnchor">Тултип</div>
    .tooltip {
      position: absolute;
      position-area: top left;
    }

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

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

Прочие условия позиционирования

  1. Помимо обычных элементов можно также использовать псевдоэлементы и элементы пользовательского интерфейса, такие как ползунок в <input type="range" >.

  2. Позиционирование работает только с видимыми в DOM элементами. Иначе говоря, элементы с display: none, visibility: hidden или content-visibility: hidden работать не будут.

Способы размещения позиционируемого элемента

Всего существует 3 разных способа разместить один элемент относительно другого:

  1. При помощи свойства position-area

  2. При помощи функции anchor()

  3. При помощи значения anchor-center

Примеры:

  1. Свойство position-area

    .tooltip {
      position-area: top left;
    }
  2. Функция anchor()

    .tooltip {
      left: anchor(right);
      bottom: anchor(bottom);
    }

    В данном примере позиционируемый элемент выравнивает свой левый край с правой стороной якоря, а нижний край с нижним. Более подробно функцию anchor() рассмотрим ниже.

  3. Значение anchor-center

    .tooltip {
      align-self: anchor-center;
      justify-self: anchor-center;
    }

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

    Значение anchor-center может быть использовано со свойствами justify-self, align-selfjustify-itemsalign-items, а также с их сокращёнными вариантами place-items и place-self.

Копаем глубже, детали отдельных свойств

anchor-name

Указывает имя якоря, к которому в дальнейшем можно будет прикрепить позиционируемый элемент. Через запятую можно указывать несколько имён.

Значения:

  • none (значение по-умолчанию) - отменяет привязку якоря и позиционируемого элемента

  • имя якоря - одно или несколько имён, перечисленных через запятую, начинающихся с двойного дефиса.

    .anchor {
      anchor-name: --myAnchor, --buttonAnchor;
    }

position-anchor

Связывает позиционируемый элемент с якорем по определённому в anchor-name имени.

Значения:

  • auto (значение по-умолчанию) – связывает элемент с другим только в том случае, если привязка была сделана неявно. Например, при помощи html атрибутов anchor и id.

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

Пример:

.tooltip {
  position-anchor: --myAnchor;
}

position-area

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

Значения:

  • none (значение по-умолчанию) - отменяет позиционирование элемента

  • top или bottom или center + left или right или center через пробел - дают возможность занять одну из 9 областей позиционирования

    .tooltip {
      position-area: right center; 
    }
  • top или bottom или left или right - дают возможность занять целую строку или колонку

    .tooltip {
      position-area: top; 
    }
  • top или bottom или left или right или center + span-top или span-bottom или span-left или span-right через пробел - дают возможность занять сразу 2 ячейки.

    .tooltip {
      position-area: top span-right; 
    }
  • top или bottom или left или right или center + span-all через пробел - дают возможность занять целую строку или колонку. По сути аналог простых top, left, right, bottom.

    .tooltip {
      position-area: right span-all; 
    }

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

position-visibility

Указывает при каких условиях позиционируемый элемент будет виден, а при каких он будет скрыт. При скрытии возникает такой же эффект как и при visibility: hidden.

Значения:

  • always (значение по‑умолчанию) — позиционируемый элемент виден всегда.

  • anchors‑visible — позиционируемый элемент виден до тех пор, пока хотя бы частично виден якорь.

  • no‑overflow — позиционируемый элемент виден до тех пор, пока он сам хотя бы немного не выходит за край экрана.

Пример:

.tooltip {
  position-visibility: no-overflow;
}

position-try-fallbacks

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

Значения:

  • none (значение по‑умолчанию) — отменяет запасные позиции.

  • flip‑block — при нехватке места элемент переместится на обратную сторону блочной оси. Если не используются свойства writing‑mode, direction и другие, меняющие направление текста, то по‑умолчанию это значение означает вертикальное позиционирование.

  • flip‑inline — при нехватке места элемент переместится на обратную сторону строчной оси. Если не используются свойства writing‑mode, direction и другие, меняющие направление текста, то по‑умолчанию это значение означает горизонтальное позиционирование.

  • flip‑start — при нехватке места элемент переместится в противоположную сторону по диагонали. Местоположение диагонали зависит от значений, определённых в свойствах direction, writing‑mode и других, меняющих направление текста.

  • position‑area значения — все значения свойства position‑area.

  • имя position‑try директивы — имя, начинающееся с двойного дефиса.

    .tooltip {
      position-try-fallbacks: --customLeft, --customRight, center, flip-block;
    }
    
    @position-try --customLeft {
      position-area: left;
      width: 100px;
      margin: 10px;
    }
    
    @position-try --customRight {
      position-area: right;
      margin-top: 10px;
    }

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

  • значения разделённые пробелом — все представленные выше значения можно указывать через пробел. В таком случае позиции будут суммироваться. К примеру возьмём position‑try‑fallbacks со значением flip‑inline flip‑block. В данной ситуации, при нехватке места, позиционируемый элемент будет перемещаться не сразу по блочной и строчной оси, а по строчной плюс блочной. То есть, если элемент находится в левом нижнем углу, то сначала он будет перемещён в правый нижний (flip‑inline), а уже затем из этой позиции будет переброшен в правый верхний (flip‑block). Эту схему я описал для простоты понимания, по итогу мы просто увидим переход по диагонали, нескольких перескоков не будет.

position-try-order

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

Значения:

  • normal (значение по-умолчанию) — используется стандартный порядок, определённый в position‑try‑fallbacks.

  • most‑width — приоритет отдаётся позициям с наибольшей шириной.

  • most‑height — приоритет отдаётся позициям с наибольшей высотой.

  • логические значения — значения, аналогичные представленным выше, но опирающиеся на направление текста.

position-try

Сокращение для свойств position-try-order и position-try-fallbacks.

Синтаксис:
position-try = position-try-order? position-try-fallbacks

Значения обоих свойств разделяются пробелом, position-try-order является необязательным.

@position-try

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

Пример:

@position-try --customLeft {
  position-area: left;
  width: 100px;
  margin: 10px;
}

Внутри директивы может быть использован строго определённый набор свойств:

  • position-anchor

  • position-area

  • inset свойства: top, left, bottom, right, inset-block-start, inset-block-end, inset-inline-start, inset-inline-end, inset-block, inset-inline, inset.

  • margin свойства: margin-top, margin-left, margin-bottom, margin-right, margin-block-start, margin-block-end, margin-inline-start, margin-inline-end, margin, margin-block, margin-inline.

  • свойства размера: width, height, min-width, min-height, max-width, max-height, block-size, inline-size, min-block-size, min-inline-size, max-block-size, max-inline-size.

  • свойства выравнивания: align-self, justify-self, place-self.

Функция anchor()

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

Пример:

.tooltip {
  position: absolute;
  position-anchor: --myAnchor;
  top: anchor(bottom);
}

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

Синтаксис:
anchor() = anchor(anchor-name? anchor-side, length-percentage?)

  • anchor-name (необязательный параметр) — значение свойства anchor‑name, которое указывает относительно какого якоря будет позиционироваться элемент.

  • anchor‑side — указывает относительно какой стороны выровнять позиционируемый элемент

    • top — относительно верхнего края якоря

    • right — относительно правого края якоря

    • left — относительно левого края якоря

    • center — относительно центра якоря. Ось центрирования соответствует используемому свойству. К примеру, для left это будет горизонтальная ось, а для top вертикальная.

    • inside — относительно той же стороны, что и у используемого свойства. К примеру, left: anchor(inside) будет аналогичен left: anchor(left).

    • outside — относительно противоположной стороны используемого свойства. К примеру, left: anchor(inside) будет аналогичен left: anchor(right).

    • проценты — относительно оси используемого свойства. К примеру, left: anchor(75%) выровняет левый край позиционируемого элемента от левого края якоря на 75% ширины якоря.

    • логические свойства — свойства, аналогичные представленным выше, но опирающиеся на направление текста

  • length‑percentage (необязательный параметр) — указывает резервное значение на случай, если якорная связка с позиционируемым элементом будет отсутствовать.

Свойства, которым доступна функция: top, left, bottom, right, inset, inset-block-start, inset-block-end, inset-block, inset-inline-start, inset-inline-end, inset-inline.

Значение anchor-side должно обязательно соответствовать оси свойства, которой оно задаётся. То есть left: anchor(right) будет работать, а вот left: anchor(top) уже нет. Ниже представлена полная таблица совместимости значений функции со свойствами.

Свойство

anchor-side значение

Все

center

Все

проценты

top и bottom

topbottomstartendself-start,self-end

left и right

leftrightstartendself-start,self-end

inset-block-start иinset-block-end

startendself-startself-end, topbottom в режимах горизонтального письма

leftrightв режимах вертикального письма

inset-inline-start и inset-inline-end

startendself-startself-end, leftright в режимах горизонтального письма

topbottom в режимах вертикального письма

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

Возвращает размер якоря (ширину или высоту).

Например:

.tooltip {
  width: anchor-size(height);
}

Если не передать ни одного параметра, то значение будет соответствовать оси свойства, для которой оно задано. Например:

  • width: anchor-size() аналогичен width: anchor-size(width).

  • top: anchor-size() аналогичен top: anchor-size(height).

Синтаксис:
anchor-size() = anchor-size(anchor-name? anchor-size? , length-percentage?)

  • anchor-name (необязательныйпараметр) — значение свойства anchor‑name, которое указывает, относительно какого якоря будет позиционироваться элемент.

  • anchor‑size (необязательный параметр) — указывает относительно какой из сторон будет вычисляться размер.

    • width — ширина якоря.

    • height — высота якоря.

    • логические свойства — свойства, аналогичные представленным выше, но опирающиеся на направление текста

  • length‑percentage (необязательный параметр) — указывает резервное значение на случай, если якорная связка с позиционируемым элементом будет отсутствовать.

Свойства, которым доступна функция:

  • inset свойства: top, left, bottom, right, inset-block-start, inset-block-end, inset-inline-start, inset-inline-end, inset-block, inset-inline, inset.

  • margin свойства: margin-top, margin-left, margin-bottom, margin-right, margin-block-start, margin-block-end, margin-inline-start, margin-inline-end, margin, margin-block, margin-inline.

  • свойства размера: width, height, min-width, min-height, max-width, max-height, block-size, inline-size, min-block-size, min-inline-size, max-block-size, max-inline-size.

Заключение

Собственно, это и весь API. Надеюсь, статья была вам полезна. Если возникли вопросы, то пишите комментарии, постараюсь своевременно ответить на все.

Теги:
Хабы:
+10
Комментарии2

Публикации

Ближайшие события