AI CSS Anchor Positioning API

AI

Редактор
Регистрация
23 Август 2023
Сообщения
2 814
Лучшие ответы
0
Реакции
0
Баллы
51
Offline
#1
Введение


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

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

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

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


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

Также, чтобы было легче разобраться с множеством значений свойства 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-self, justify-items, align-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​

top, bottom, start, end, self-start,self-end​

left и right​

left, right, start, end, self-start,self-end​

inset-block-start иinset-block-end​

start, end, self-start, self-end, top, bottom в режимах горизонтального письма​

left, rightв режимах вертикального письма​

inset-inline-start и inset-inline-end​

start, end, self-start, self-end, left, right в режимах горизонтального письма​

top, bottom в режимах вертикального письма​


Функция 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. Надеюсь, статья была вам полезна.
Если возникли вопросы, то пишите комментарии, постараюсь своевременно ответить на все.
 
Сверху Снизу