Позиционирование
Обычно элементы стоят в потоке документа: каждый следующий блок идёт под предыдущим, строчные элементы — друг за другом в строке. Свойство position позволяет сдвинуть элемент, наложить его поверх других или прикрепить к краю окна.
Значения position
| Значение | Что делает |
|---|---|
static | Обычное место в потоке. Значение по умолчанию |
relative | Сдвиг относительно своего обычного места |
absolute | Элемент выходит из потока и ставится по координатам внутри родителя |
fixed | Прикреплён к окну браузера и не прокручивается |
sticky | Едет вместе со страницей, а у края окна «прилипает» |
Координаты задают свойства top, right, bottom и left — расстояние от соответствующего края. У static они не действуют.
relative — сдвиг на месте
Элемент с position: relative сдвигается, но его прежнее место остаётся занятым, и соседи не двигаются:
<style>
.box { padding: 8px; background: lavender; margin-bottom: 4px; }
.moved { position: relative; top: 10px; left: 40px; background: gold; }
</style>
<div class="box">Первый</div>
<div class="box moved">Сдвинут на 10px вниз и 40px вправо</div>
<div class="box">Третий остался на месте</div>Жёлтый блок наехал на третий: для остальных элементов он по-прежнему стоит на старом месте.
absolute — по координатам внутри родителя
Элемент с position: absolute убирается из потока и ставится по координатам. Отсчёт идёт от ближайшего предка, у которого position не static, — поэтому родителю обычно дают position: relative:
<style>
.card { position: relative; padding: 16px; background: whitesmoke; }
.badge { position: absolute; top: 8px; right: 8px; padding: 2px 8px; background: crimson; color: white; }
</style>
<div class="card">
<span class="badge">Новинка</span>
Карточка товара. Метка прижата к правому верхнему углу.
</div>Так делают значки, кнопки «закрыть», подписи поверх картинок. Прикрепить элемент к блоку, внутри которого он не лежит, позволяет привязка к якорю — урок «Привязка к якорю».
inset — все стороны сразу
Свойство inset — сокращение для четырёх координат. inset: 0 растягивает абсолютный элемент на весь родитель — удобно для затемняющего слоя:
<style>
.photo { position: relative; height: 100px; background: steelblue; }
.shade { position: absolute; inset: 0; background: rgb(0 0 0 / 0.4); color: white; padding: 12px; }
</style>
<div class="photo">
<div class="shade">Слой поверх всего блока</div>
</div>fixed и sticky
fixed прикрепляет элемент к окну: так делают кнопку «наверх» или чат в углу. sticky держит элемент на месте, пока его контейнер прокручивается. Прокрутите список в примере:
<style>
.list { height: 140px; overflow: auto; border: 1px solid silver; }
.list h3 { position: sticky; top: 0; margin: 0; padding: 6px 8px; background: lightskyblue; }
.list p { margin: 0; padding: 6px 8px; }
</style>
<div class="list">
<h3>Буква А</h3><p>Анна</p><p>Антон</p><p>Арсений</p>
<h3>Буква Б</h3><p>Борис</p><p>Богдан</p><p>Белла</p>
<h3>Буква В</h3><p>Вера</p><p>Виктор</p>
</div>Для sticky обязательно указать хотя бы одну координату, например top: 0, — иначе прилипать некуда.
Частая ошибка
Если ни у одного предка нет position, абсолютный элемент отсчитывает координаты от всей страницы и улетает в её угол:
<style>
.card { padding: 16px; background: whitesmoke; margin-top: 40px; }
.badge { position: absolute; top: 8px; right: 8px; background: crimson; color: white; }
</style>
<div class="card">
<span class="badge">Где я?</span>
У карточки нет position: relative.
</div>Метка оказалась в углу всего примера, а не карточки. Добавьте родителю position: relative.