Position
Схема позиционирования, привязка к краям и порядок наложения.
Схема позиционирования
| Класс | CSS | Назначение |
|---|---|---|
.gr-static | position: static | Обычный поток — значение по умолчанию |
.gr-relative | position: relative | Система отсчёта для вложенных абсолютных элементов |
.gr-absolute | position: absolute | Изъят из потока, считается от ближайшего позиционированного предка |
.gr-fixed | position: fixed | Привязан к окну |
.gr-sticky | position: sticky | Липнет к краю при прокрутке; требует хотя бы одного значения top/bottom |
Привязка к краям
| Класс | CSS |
|---|---|
.gr-inset-0 | inset: 0 — растянут по всем четырём краям |
.gr-inset-auto | inset: auto |
.gr-inset-x-0 | inset-inline: 0 — оба края строки |
.gr-inset-y-0 | inset-block: 0 — верх и низ |
.gr-top-0, .gr-bottom-0 | Верхний / нижний край — 0 |
.gr-top-auto, .gr-bottom-auto | То же — auto |
.gr-start-0, .gr-end-0 | inset-inline-start / inset-inline-end — 0 |
.gr-start-auto, .gr-end-auto | То же — auto |
Боковая привязка — только логическая. Пара
.gr-start-0 / .gr-end-0 держится начала
и конца строки: в LTR это левый и правый край, в RTL они меняются
местами сами. Физические .gr-left-* /
.gr-right-* удалены вместе с остальными физическими
сторонами; краю, который обязан быть буквальным — например кнопке
«закрыть», держащей угол окна при любом направлении письма, — нужен
свой CSS. Верх и низ (.gr-top-0,
.gr-bottom-0) физические: блочная ось в RTL
не разворачивается. Осевые .gr-inset-x-0
и .gr-inset-y-0 одинаковы в обоих направлениях —
у них обе стороны равны нулю.
Порядок наложения
| Класс | CSS |
|---|---|
.gr-z-0 … .gr-z-50 | z-index с шагом 10 |
.gr-z-auto | z-index: auto |
Шаг 10 оставляет место между ступенями: своё промежуточное значение вписывается обычным CSS, не трогая библиотеку.
Адаптивные варианты
Суффикс брейкпоинта есть только у самой схемы позиционирования:
.gr-static-md, .gr-relative-lg,
.gr-absolute-sm, .gr-fixed-xl,
.gr-sticky-md. У inset и z-index
адаптивных вариантов нет — на практике они не нужны.
<!-- в потоке на мобильном, липнет от 768px -->
<nav class="gr-static gr-sticky-md gr-top-0">…</nav>
Примеры использования
Ходовые задачи позиционирования, собранные из утилит этого модуля вместе
с соседями по библиотеке: флекс- и грид-выравниванием ядра, фонами,
прозрачностью и pointer-events. Новых классов ни один рецепт
не требует — и в этом суть: несколько осевых утилит в сочетаниях дают
больше вариантов, чем алфавит готовых точечных классов, по одному
на каждый случай.
Бейдж в углу картинки
Классическая пара: родителю — .gr-relative, бейджу —
.gr-absolute с привязкой .gr-top-0 .gr-end-0
и отступом от угла .gr-m-2. Родитель зауживается до картинки
классом .gr-w-fit — без него блок растянулся бы на всю
колонку, и бейдж повис бы у её дальнего края, а не у края картинки.
<div class="gr-relative gr-w-fit">
<img class="gr-radius-4" src="chair.jpg" alt="Кресло из ротанга" width="280" height="200">
<span class="gr-badge gr-badge-danger gr-absolute gr-top-0 gr-end-0 gr-m-2">−30%</span>
</div>
.gr-absolute .gr-top-0 .gr-end-0 внутри .gr-relativeРазмещение по девяти точкам
Сетка размещений, знакомая по большим библиотекам, — углы, середины сторон
и центр. Углы держит привязка к краям. Всё, где участвует центр, делает
слой .gr-absolute .gr-inset-0 с выравниванием: слой растянут
по родителю, .gr-flex-center и .gr-flex-items-*
ставят содержимое в нужную точку, а центр обеих осей ещё короче —
.gr-grid-place-center. Слой перекрывал бы клики
по картинке, поэтому ему — .gr-pointer-events-none;
если внутри слоя есть кнопка или ссылка, клики ей возвращает
.gr-pointer-events-auto.
<div class="gr-relative gr-w-fit">
<img class="gr-radius-4" src="chair.jpg" alt="" width="360" height="257">
<!-- углы: привязка к краям, слой не нужен -->
<span class="gr-badge gr-absolute gr-top-0 gr-start-0 gr-m-2">top-start</span>
<span class="gr-badge gr-absolute gr-top-0 gr-end-0 gr-m-2">top-end</span>
<span class="gr-badge gr-absolute gr-bottom-0 gr-start-0 gr-m-2">bottom-start</span>
<span class="gr-badge gr-absolute gr-bottom-0 gr-end-0 gr-m-2">bottom-end</span>
<!-- середины сторон и центр: слой во весь родитель + выравнивание -->
<div class="gr-absolute gr-inset-0 gr-flex gr-flex-center gr-flex-items-start gr-pointer-events-none">
<span class="gr-badge gr-m-2">top-center</span>
</div>
<div class="gr-absolute gr-inset-0 gr-flex gr-flex-start gr-flex-items-center gr-pointer-events-none">
<span class="gr-badge gr-m-2">center-start</span>
</div>
<div class="gr-absolute gr-inset-0 gr-grid-place-center gr-pointer-events-none">
<span class="gr-badge">center</span>
</div>
<div class="gr-absolute gr-inset-0 gr-flex gr-flex-end gr-flex-items-center gr-pointer-events-none">
<span class="gr-badge gr-m-2">center-end</span>
</div>
<div class="gr-absolute gr-inset-0 gr-flex gr-flex-center gr-flex-items-end gr-pointer-events-none">
<span class="gr-badge gr-m-2">bottom-center</span>
</div>
</div>
Растянутые размещения
Те же кирпичи в другой паре — «край + ось» вместо «край + край» — дают
растянутые варианты. .gr-top-0 .gr-inset-x-0 — полоса
во всю ширину по верхнему краю; .gr-bottom-0 .gr-inset-x-0 —
классическая подпись к фотографии; .gr-start-0 или
.gr-end-0 с .gr-inset-y-0 — колонка во всю
высоту. Растяжение по всем четырём краям сразу — .gr-inset-0,
уже знакомое по слоям выравнивания и затемнению. Специальных классов
«полоса» или «колонка» в библиотеке нет, и они не нужны: край называет
одна утилита, растяжение — другая.
<!-- полосы во всю ширину -->
<div class="gr-relative gr-w-fit">
<img class="gr-radius-4" src="chair.jpg" alt="" width="280" height="200">
<div class="gr-absolute gr-top-0 gr-inset-x-0 gr-bg-black gr-text-white gr-opacity-75 gr-p-2 gr-text-center">top + inset-x</div>
<div class="gr-absolute gr-bottom-0 gr-inset-x-0 gr-bg-black gr-text-white gr-opacity-75 gr-p-2 gr-text-center">bottom + inset-x</div>
</div>
<!-- колонки во всю высоту -->
<div class="gr-relative gr-w-fit">
<img class="gr-radius-4" src="chair.jpg" alt="" width="280" height="200">
<div class="gr-absolute gr-start-0 gr-inset-y-0 gr-bg-black gr-text-white gr-opacity-75 gr-p-2 gr-flex gr-flex-items-center">start</div>
<div class="gr-absolute gr-end-0 gr-inset-y-0 gr-bg-black gr-text-white gr-opacity-75 gr-p-2 gr-flex gr-flex-items-center">end</div>
</div>
.gr-inset-x-0», колонки — «край + .gr-inset-y-0»Вынос за край
Элемент снаружи родителя или наполовину за его углом — счётчик
непрочитанного на кнопке, ярлык сбоку от блока. В шкале краёв таких
значений нет намеренно: случай редкий, и готовые классы под «−0.5rem»
и «100%» раздували бы CSS. Их дают
произвольные значения —
.gr-top-[-0.5rem] ставит верхний край выше родителя,
а .gr-end-[100%] выносит элемент целиком за начало строки:
в LTR его правый край встаёт на левый край родителя, в RTL картинка
разворачивается сама. Вертикальный центр снаружи — тот же слой
с выравниванием, что и в девяти точках, только вместо
.gr-start-0 у него .gr-end-[100%].
<!-- счётчик наполовину за углом кнопки -->
<button class="gr-btn gr-relative" type="button">
Входящие
<span class="gr-badge gr-badge-count gr-badge-danger gr-absolute gr-top-[-0.5rem] gr-end-[-0.5rem]">3</span>
</button>
<!-- ярлыки целиком снаружи, по вертикальному центру краёв -->
<div class="gr-relative gr-w-fit">
<img class="gr-radius-4" src="chair.jpg" alt="" width="280" height="200">
<div class="gr-absolute gr-inset-y-0 gr-end-[100%] gr-flex gr-flex-items-center">
<span class="gr-badge gr-m-2">снаружи</span>
</div>
<div class="gr-absolute gr-inset-y-0 gr-start-[100%] gr-flex gr-flex-items-center">
<span class="gr-badge gr-m-2">снаружи</span>
</div>
</div>
.gr-end-[100%] / .gr-start-[100%]Липкая шапка
.gr-sticky липнет к ближайшему прокручиваемому предку.
На странице это обычно само окно — шапке хватает
.gr-sticky .gr-top-0 .gr-z-40 и непрозрачного фона;
в демонстрации прокручивается рамка с .gr-overflow-y-auto,
поэтому шапка останавливается у её верха. Без .gr-top-0
липкость не работает вовсе: браузеру не сказано, у какого края замереть.
<!-- прокручиваемая рамка — деталь демонстрации:
на странице липкую шапку прокручивает само окно -->
<div class="gr-overflow-y-auto gr-border gr-radius-4" style="height: 180px">
<header class="gr-sticky gr-top-0 gr-z-10 gr-bg-surface gr-border-b gr-p-2 gr-font-semibold">
Журнал наблюдений
</header>
<p class="gr-p-2 gr-m-0">Запись первая…</p>
</div>
.gr-sticky .gr-top-0 остаётся у верхаЗапись первая: прокрутка ещё не началась, шапка стоит там же, где стояла бы и без липкости.
Запись вторая: как только её верх дошёл бы до края рамки, шапка осталась на месте, а текст ушёл под неё.
Запись третья: непрозрачный фон шапке обязателен — иначе прокручиваемый текст просвечивал бы сквозь неё.
Запись четвёртая: .gr-z-10 держит шапку над содержимым, у которого случится свой контекст наложения.
Запись пятая: дальше прокручивать некуда, но шапка так и не сдвинулась.
Затемнение под модальным окном
Два слоя над содержимым, разведённые по ступеням: затемнению —
.gr-z-40, окну — .gr-z-50. В демонстрации оба
заперты в рамке классом .gr-absolute; на настоящей странице
затемнение берёт .gr-fixed .gr-inset-0 — привязку к окну
браузера. Собирать эту пару руками нужно редко:
модальное окно на <dialog>
красит подложку само через ::backdrop.
<!-- в демонстрации слои держит рамка с .gr-relative;
на странице у затемнения вместо .gr-absolute — .gr-fixed -->
<div class="gr-relative">
… содержимое страницы …
<div class="gr-absolute gr-inset-0 gr-z-40 gr-bg-black gr-opacity-50"></div>
<div class="gr-absolute gr-inset-0 gr-z-50 gr-grid-place-center">
<div class="gr-bg-surface gr-radius-4 gr-shadow-lg gr-p-3">Окно</div>
</div>
</div>
.gr-z-40 над страницей, окно .gr-z-50 над затемнениемСтраница под затемнением
Текст читается сквозь полупрозрачный слой, но заметно тускнеет.