Относительное позиционирование

position: relative сдвигает элемент от его обычного места через top, right, bottom и left, но при этом место, которое он занимал бы без сдвига, остаётся зарезервированным в разметке - и делает элемент точкой отсчёта для любых absolute-потомков внутри себя.

Попробуй прямо сейчас: смени у .shifted значение left на right с тем же числом - блок сдвинется в противоположную сторону, хотя число не изменилось.

top, right, bottom, left: в какую сторону они сдвигают

В обзорном уроке про position уже говорилось, что relative сдвигает элемент от обычного места. Но направление сдвига не всегда очевидно: top и left толкают элемент в сторону своего названия (top - вниз от верхнего края, left - вправо от левого), а вот right и bottom работают НАОБОРОТ - они отсчитывают расстояние ОТ соответствующего края, поэтому right толкает элемент ВЛЕВО, а bottom - ВВЕРХ. Если задать одновременно left и right (или top и bottom), побеждает left (top), а right (bottom) будет полностью проигнорирован.

position: relative; left: 20px; - элемент сдвинется на 20px вправо от своего обычного места.

position: relative; right: 20px;, ожидая сдвиг вправо - right толкает в противоположную сторону, элемент сдвинется на 20px ВЛЕВО, а не вправо.

Место в потоке сохраняется - главное отличие от absolute

Смещённый через relative элемент визуально "уезжает" со своего места, но само место в разметке остаётся за ним зарезервированным - как будто там по-прежнему стоит невидимый двойник элемента на исходной позиции. Соседние элементы ведут себя так, будто сдвига вообще не было. Это ключевое отличие от position: absolute, который убирает элемент из потока полностью - соседи "не знают", что элемент вообще существовал на этом месте.

Проценты в top/bottom считаются от высоты содержащего блока, а в left/right - от его ширины: например, top: 10% в контейнере высотой 200px сдвинет элемент на 20px, а left: 10% в том же контейнере, но шириной 400px - уже на 40px, хотя проценты одинаковые.

position: relative; top: 20px; - элемент сдвинется, но пустое место на его исходной позиции останется в разметке, влияя на высоту родителя и положение соседей.

position: relative;, ожидая, что соседние элементы "подвинутся" на освободившееся место сдвинутого элемента - при relative место НЕ освобождается, для такого поведения нужен position: absolute (или flexbox/grid).

relative без смещения: точка отсчёта для absolute-потомков

Самое частое практическое применение relative - вовсе не сдвиг, а создание "точки отсчёта" для потомков. Если задать родителю position: relative без единого top/left (то есть без визуального смещения вообще), он становится containing block - точкой, относительно которой будут позиционироваться любые вложенные элементы с position: absolute. Без этого шага absolute-потомок отсчитывался бы от всей страницы, а не от нужного блока.

.card { position: relative; } без top/left, чтобы вложенный .badge { position: absolute; top: 8px; right: 8px; } прилип именно к углу карточки.

.badge { position: absolute; top: 8px; right: 8px; } без position: relative у родителя-карточки - бейдж уедет в угол всей страницы, а не карточки.

Из истории Связка position: relative на родителе (без смещения) плюс position: absolute на потомке была единственным способом "привязать" один элемент к другому с самого появления этих значений в спецификации CSS2 1998 года - и остаётся стандартной практикой почти 30 лет. Но в июне 2023 года W3C опубликовал первый черновик совсем нового модуля - CSS Anchor Positioning, который позволяет привязать элемент к ЛЮБОМУ другому элементу страницы без вложенности и без relative вовсе. Спецификация дошла до браузеров необычно быстро: уже в Chrome 125 в 2024 году - всего через год после черновика, тогда как CSS-переменным для широкой поддержки понадобилось 4 года. Так что привычный приём из этого урока получил младшего конкурента - но сам никуда не денется ещё долго из-за старых браузеров.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Путают направление right и bottom Ожидают сдвиг вправо/вниз, а элемент уезжает влево/вверх Помнить: right и bottom отсчитывают расстояние ОТ своего края, а не куда толкать
Задают одновременно left и right (или top и bottom) right (bottom) полностью игнорируется, работает только left (top) Указывать только одно значение на ось - left ИЛИ right, top ИЛИ bottom
Ждут, что соседи займут место сдвинутого relative-элемента Место остаётся зарезервированным, соседи не двигаются Использовать position: absolute (или flexbox/grid), если место должно освобождаться
Забывают position: relative у родителя перед position: absolute у потомка absolute-элемент позиционируется от всей страницы, а не от нужного блока Добавить родителю position: relative, даже без top/left

Шпаргалка

Что нужноКак сделать
Сдвинуть вправо / влевоleft: Npx; / right: Npx;
Сдвинуть вниз / вверхtop: Npx; / bottom: Npx;
Сохранить место в разметке при сдвигеposition: relative;
Задать точку отсчёта для absolute-потомковposition: relative; (без top/left у самого родителя)
Проценты в top/bottom считаются отвысоты содержащего блока
Проценты в left/right считаются отширины содержащего блока

Коротко: отвечаем на вопросы

Почему right сдвигает элемент влево, а не вправо?

Каждое из свойств top/right/bottom/left задаёт расстояние ОТ соответствующего края элемента до его обычного положения, а не направление движения. right: 20px значит "правый край должен оказаться на 20px левее исходного места" - отсюда и сдвиг влево. То же самое с bottom - он сдвигает элемент вверх.

Зачем ставить position: relative, если не нужен визуальный сдвиг?

Самая частая причина - сделать элемент точкой отсчёта (containing block) для вложенных элементов с position: absolute. Без этого absolute-потомок отсчитывался бы от всей страницы, а не от нужного родительского блока - например, бейдж на карточке товара.

Что будет, если задать и left, и right одному relative-элементу?

Победит left - именно он определит итоговый сдвиг, а right будет полностью проигнорирован. То же самое правило действует для пары top и bottom: побеждает top.

Категория
css
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×