18 Модуль 4 Коробки и раскладка 15 мин урок 18 из 25

Позиционирование: выходим из потока

static, relative, absolute, fixed и sticky: от чего считаются координаты, как работает z-index и что такое контекст наложения.

Что ты научишься делать

  • Поставишь бейдж точно на угол карточки
  • Сделаешь шапку, которая прилипает к верху при прокрутке
  • Разберёшься, почему z-index иногда «не работает»

#Пять значений position

Свойство position определяет, участвует ли элемент в обычном потоке и от чего отсчитываются его координаты top, right, bottom, left.

Важно: пока position равен static (а это значение по умолчанию), координаты не работают вообще. Написал top: 20px и ничего не произошло — почти всегда причина в этом.

Лаборатория позиционирования

Переключаешь position — видно, от чего элемент отсчитывает координаты.

ЗначениеТочка отсчёта
staticОбычный поток, координаты не работают
relativeСвоё же исходное место
absoluteБлижайший позиционированный предок
fixedОкно браузера
stickyПоток, пока не упрётся в заданный край

#relative: сдвиг от самого себя

relative сдвигает элемент относительно его собственного исходного места. Важная деталь: место в потоке за ним сохраняется. Соседи ведут себя так, будто элемент никуда не двигался.

Но главная роль relative другая — он делает элемент точкой отсчёта для абсолютно спозиционированных детей. Именно так его используют в девяти случаях из десяти.

#absolute: от ближайшего позиционированного предка

absolute вынимает элемент из потока: соседи занимают его место, будто его нет. Координаты считаются от ближайшего предка, у которого position не static.

Если такого предка нет, точкой отсчёта становится вся страница — и элемент часто уезжает совсем не туда, куда ожидалось.

CSSКлассическая пара
.card {  position: relative;   /* точка отсчёта */}.card__badge {  position: absolute;   /* считает координаты от .card */  top: 12px;  right: 12px;}
Бейдж на карточке
В песочницу

#fixed: привязка к окну

fixed тоже выходит из потока, но точка отсчёта у него всегда одна — окно браузера. При прокрутке элемент остаётся на месте.

Так делают кнопку «наверх», плавающую кнопку заказа, модальные окна.

#sticky: липкий заголовок

sticky — гибрид. Элемент ведёт себя как обычный, пока прокрутка не дойдёт до заданного края. Тогда он «прилипает» и едет вместе с экраном — но только пока виден его родитель.

Для работы обязательно нужны две вещи: значение sticky и хотя бы одна координата, например top: 0. Без координаты ничего не произойдёт.

Прокрути пример внутри рамки
В песочницу

#z-index и контекст наложения

Когда элементы накладываются, порядок определяет z-index: больше число — выше слой. Но работает он только у позиционированных элементов, то есть у тех, где position не static.

Дальше начинается самое интересное. z-index сравнивается не по всей странице, а внутри своего контекста наложения.

Новый контекст создаёт любой из этих признаков:

  • позиционированный элемент с любым z-index, кроме auto;
  • opacity меньше единицы;
  • transform, filter, backdrop-filter;
  • will-change, isolation: isolate.

Так не надо

.modal {
  z-index: 999999;
}
/* всё равно под шапкой */

Число ничего не решает, если элемент лежит внутри чужого контекста наложения. Всё, что было создано родителем, сравнивается как единое целое.

Так надо

/* Выносим модалку в конец body,
   чтобы у неё не было «дома»-родителя */
body > .modal {
  position: fixed;
  z-index: 100;
}

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

Где спотыкаются почти все

У родителя забыт position: relative

Почему Абсолютный ребёнок начинает считать координаты от всей страницы и уезжает в её угол.

Как надо Всегда ставь пару: relative родителю, absolute ребёнку.

z-index задан элементу со static

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

Как надо Добавь position: relative — этого достаточно, элемент даже не сдвинется.

position: sticky без координаты

Почему Браузеру не сказали, к какому краю прилипать. Ошибки нет, эффекта тоже.

Как надо Обязательно задай top, bottom, left или right.

Раскладка страницы сделана на absolute

Почему Абсолютные элементы не знают друг о друге и не подстраиваются под содержимое. При любом изменении текста вёрстка наезжает сама на себя.

Как надо Позиционирование — для точечных вещей: бейджей, подсказок, оверлеев. Раскладка — флексы и гриды.

Позиционирование positioning
Управление положением элемента через position и координаты.
Содержащий блок containing block
Элемент, от которого считаются координаты абсолютно спозиционированного потомка.
Выход из потока out of flow
Элемент перестаёт занимать место, соседи ведут себя так, будто его нет.
Контекст наложения stacking context
Область, внутри которой сравниваются значения z-index.
Липкое позиционирование sticky
Элемент прилипает к краю при прокрутке, пока виден его родитель.

Проверь себя

  1. От чего считает координаты элемент с <code>position: absolute</code>?

    Если такого предка нет, точкой отсчёта становится вся страница — отсюда и уехавшие бейджи.

  2. Что нужно, чтобы заработал <code>position: sticky</code>?

    Без <code>top</code> или другой координаты браузер не знает, к чему прилипать, и ничего не делает.

  3. Почему <code>z-index: 9999</code> может не поднять элемент наверх?

    Слои сравниваются внутри контекста. Родитель с <code>opacity</code> или <code>transform</code> создаёт свой «дом», из которого ребёнку не выбраться.

  4. Чем relative отличается от absolute по влиянию на соседей?

    <code>relative</code> только рисует элемент со смещением — его исходное место остаётся занятым.

  5. Что создаёт новый контекст наложения?

    Верных вариантов несколько.

    Отступы к слоям отношения не имеют. А прозрачность, трансформации и позиционирование с явным <code>z-index</code> — создают.

Задание

Бейдж и липкая шапка

Две задачи в одном примере:

  • поставь бейдж .badge в правый верхний угол карточки .card — используй пару relative/absolute;
  • сделай шапку .head липкой: при прокрутке списка она должна оставаться сверху.
Открыть в песочнице
    Подсказка 1

    Сначала родителю: .card { position: relative; }. Только после этого бейдж сможет считать координаты от карточки.

    Подсказка 2

    Липкая шапка — это два свойства сразу: .head { position: sticky; top: 0; }

    Показать решение
    HTMLindex.html
    <div class="box">  <h2 class="head">Меню на сегодня</h2>  <article class="card">    <span class="badge">новинка</span>    <h3>Раф на кокосовом</h3>    <p>Мягкий и сладкий.</p>  </article>  <p>Эспрессо</p>  <p>Американо</p>  <p>Капучино</p>  <p>Латте</p>  <p>Флэт уайт</p>  <p>Мокко</p>  <p>Раф классический</p></div>
    CSSstyle.css
    * { box-sizing: border-box; }.box {  height: 260px;  overflow-y: auto;  border: 1px solid #ddd;  border-radius: 10px;}.head {  position: sticky;  top: 0;  margin: 0;  padding: 10px 14px;  font-size: 16px;  color: #fff;  background: #6544e0;}.card {  position: relative;  margin: 14px;  padding: 14px;  background: #f5f5fa;  border-radius: 12px;}.badge {  position: absolute;  top: -8px;  right: -8px;  padding: 4px 10px;  font-size: 12px;  color: #fff;  background: #e0396a;  border-radius: 999px;}.box p {  margin: 0;  padding: 10px 14px;  border-bottom: 1px solid #eee;}

    Проверь себя