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 у родителя-карточки - бейдж уедет в угол всей страницы, а не карточки.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Путают направление 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.