Коротко: чтобы один блок (бейдж, подпись, затемнение) «лёг» поверх другого, нужны два инструмента — position и z-index. В статье — все способы с примерами, три практических сценария, разбор ловушек и проверка знаний.
Что такое «наложить блок на блок» простыми словами
Страница — это слои. Представьте лист бумаги и наклейки. Лист — родительский блок, наклейки — дочерние элементы. «Наложить» = положить одну наклейку поверх другой и точно её разместить.
По умолчанию элементы не накладываются: они идут друг за другом сверху вниз (или слева направо, если строчные). Чтобы включить «слои», мы меняем поведение элемента через CSS.
Важно понимать: наложение — это всегда два шага.
- Позиционирование — говорим браузеру, от чего считать положение блока (от себя, от родителя, от окна).
- Порядок слоёв — если блоков несколько, задаём, кто выше через
z-index.
Шаг 1. position — «от чего считать положение»
Свойство position имеет пять значений. Разберём каждое на вкладках — с примерами и подводными камнями.
static — обычное поведение. Блок стоит «в потоке», как строчка в тетради. Смещения (top/left) не действуют, z-index не действует.
.box { position: static; } /* значение по умолчанию */z-index «не работает», чаще всего элемент остался static. Проверьте это первым делом.relative — блок остаётся на своём месте, но его можно сдвинуть. Главная суперспособность: он становится точкой отсчёта для дочерних absolute.
.card {
position: relative; /* точка отсчёта для бейджа */
}
.badge {
position: absolute;
top: 8px; left: 8px;
}Сдвиг при этом считается от исходного места блока:
.nudge { position: relative; top: 4px; left: 2px; }absolute — блок «выпадает» из потока и позиционируется относительно ближайшего родителя с position, отличным от static. Если такого родителя нет — относительно окна (что почти всегда не то, что нужно).
.card { position: relative; } /* обязательный родитель */
.card__label {
position: absolute;
left: 0; right: 0; bottom: 0;
}Чаще всего так делают: бейджи, подписи поверх фото, иконки в углу, затемнение фона.
fixed — блок «прилипает» к окну браузера и не двигается при прокрутке. Классика: кнопка «наверх», плавающая панель чата, мобильное меню.
.to-top {
position: fixed;
right: 20px; bottom: 20px;
z-index: 100;
}padding-bottom), иначе последние строки «спрячутся» под кнопкой.sticky — «липкий»: сначала как обычный, но при прокрутке закрепляется в заданной точке. Нужен хотя бы один top/left/right/bottom.
.toc {
position: sticky;
top: 20px; /* обязательно, иначе не закрепится */
}Во flex‑контейнере может понадобиться align-self: flex-start, иначе «липкость» не сработает.
Шаг 2. Смещения: top, right, bottom, left
Смещения работают у любого position, кроме static. Есть короткая запись inset:
.overlay { position: absolute; inset: 0; } /* растянуть по всем сторонам */
.overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } /* то же самое */| Свойство | Что делает |
|---|---|
top |
смещение от верхнего края родителя |
right |
от правого края |
bottom |
от нижнего края |
left |
от левого края |
inset |
сразу все стороны |
Практика: три сценария, которые нужны чаще всего
Сценарий 1. Бейдж на карточке товара
- Оберните картинку и бейдж в общий контейнер.
- Контейнеру задайте
position: relative. - Бейджу —
absoluteи смещение в угол. - При необходимости добавьте
z-index.
<div class="card">
<img src="shoe.jpg" alt="">
<span class="badge">−30%</span>
</div>.card { position: relative; display: inline-block; }
.card img { display: block; width: 100%; }
.badge {
position: absolute; top: 10px; left: 10px;
background: #992222; color: #fff;
padding: 4px 10px; border-radius: 8px;
font: 600 13px/1 system-ui;
}Сценарий 2. Текст поверх фотографии
.hero { position: relative; }
.hero img { display: block; width: 100%; }
.hero__title {
position: absolute; inset: auto 0 0 0;
padding: 20px; color: #fff;
background: linear-gradient(transparent, rgba(0,0,0,.7));
}Градиент снизу делает текст читаемым на любом фото. Это важная деталь: без затемнения белый текст «теряется» на светлых участках.
Сценарий 3. Модальное окно
.modal {
position: fixed; inset: 0; z-index: 1000;
display: flex; align-items: center; justify-content: center;
background: rgba(0,0,0,.5);
}
.modal__box { background: #fff; padding: 24px; border-radius: 16px; }Оверлей растянут на весь экран, а окно центрируется flex‑ом. Такой слой всегда «выше» контента благодаря z-index.
relative. Слой поверх — absolute (или fixed для окна). Смещения — top/left/right/bottom. При конфликте слоёв — z-index.z-index: порядок слоёв и его ловушки
z-index — «этаж» блока. Чем больше число, тем выше он рисуется. Работает у элементов с позиционированием (и во flex/grid‑контекстах).
.tooltip { position: absolute; z-index: 10; }
.modal { position: fixed; z-index: 1000; }Контексты наложения (stacking contexts)
Иногда высокий z-index «не помогает». Причина — новый контекст наложения у родителя (например, из‑за transform, opacity < 1 или своего z-index). Внутри такого родителя свои «этажи», и он не может «перепрыгнуть» соседний контекст.
position + z-index) или уберите у него свойства, создающие контекст (transform, opacity, filter), если они не нужны.Частые ошибки: причина → решение
| Симптом | Причина | Решение |
|---|---|---|
absolute «улетел» в угол страницы |
у родителя нет позиционирования | родителю position: relative |
z-index не действует |
элемент static |
задать relative/absolute/fixed |
| Блок прыгает при изменении ширины | нет размеров/пропорций | aspect-ratio или min-height |
| Fixed перекрывает контент | нет отступа снизу | padding-bottom у страницы |
| Sticky не «липнет» | не задан top или мешает flex |
добавить top, align-self: flex-start |
Проверьте себя
absolute‑блок считался от него?
z-index: 9999 иногда не поднимает блок?
Вопросы и ответы
absolute привязан к родителю и уезжает со страницей при прокрутке. fixed привязан к окну браузера и остаётся на месте.
Родитель relative; блок absolute с top:50%; left:50%; transform: translate(-50%,-50%).
Частично — отрицательными margin, но это «костыль». Для предсказуемого результата используйте position.
Короткая запись для top/right/bottom/left. inset: 0 растягивает блок по всем сторонам родителя.
Не задан top (или другая сторона), либо родитель во flex не даёт элементу «растянуться». Добавьте top и align-self: flex-start.
Когда можно решить обычным потоком или flex/grid. Не плодите лишние абсолютные элементы — их сложнее поддерживать и они «ломают» адаптив.
Итоги
- Наложение =
position+z-index. - Родителю —
relative, слою —absolute/fixed. - Смещения:
top/right/bottom/leftилиinset. z-indexработает только при не‑static.- Следите за контекстами наложения и адаптивом.

Комментарии
Пока комментариев нет — будьте первым, кто поделится мнением.