← HTML & CSS/Позиционирование элементов#22 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: старт в frontendПрактика: DOM и событияТермин: DOMМаршрут: старт с нуля

Позиционирование элементов

Меню, которое остаётся наверху при прокрутке. Значок "Новое!" в углу карточки. Модальное окно по центру экрана. Всё это — CSS-позиционирование. Пять значений position, и каждое решает свою задачу.

position: static (по умолчанию)

Все элементы изначально статичны — они стоят в нормальном потоке: один за другим, сверху вниз (block) или слева направо (inline). Свойства top, left, right, bottom при static не работают.

div { position: static; }  /* Это поведение по умолчанию */

position: relative

Элемент остаётся в потоке, но может быть сдвинут от своего нормального места.

.badge {
  position: relative;
  top: 5px;    /* Сдвиг вниз от нормального места */
  left: -3px;  /* Сдвиг влево */
}

Важно: место в потоке сохраняется — соседние элементы не двигаются.

Главное применение relative — создать контекст позиционирования для дочерних absolute-элементов.

position: absolute

Элемент вырывается из потока — соседи его не видят, он парит над ними. Позиционируется относительно ближайшего предка с position не равным static.

/* Родитель — контекст позиционирования */
.card {
  position: relative;  /* Без этого absolute уйдёт к body! */
}

/* Значок в углу карточки */
.card .badge {
  position: absolute;
  top: 8px;
  right: 8px;
  background: red;
  border-radius: 50%;
}

Если у элемента нет positioned-предка, он позиционируется относительно <html>.

position: fixed

Привязан к вьюпорту (экрану), не к странице. Не скроллится вместе с контентом.

/* Шапка сайта, которая всегда вверху */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;  /* или width: 100% */
  z-index: 100;
  background: white;
}

/* Кнопка "Наверх" в правом нижнем углу */
.scroll-top-btn {
  position: fixed;
  bottom: 24px;
  right: 24px;
}

Проблема: fixed элемент перекрывает контент. Нужно добавлять padding-top к body, равный высоте хедера.

position: sticky

Гибрид: ведёт себя как relative, пока не достигнет указанного порога при скролле — тогда "прилипает" как fixed.

/* Заголовок таблицы, который прилипает при скролле */
thead th {
  position: sticky;
  top: 0;
  background: white;
}

/* Боковая навигация, которая следует за скроллом */
.sidebar {
  position: sticky;
  top: 80px;  /* 80px от верха вьюпорта */
}

z-index — слои

Определяет порядок по оси Z (что поверх чего). Работает только для позиционированных элементов.

.dropdown { z-index: 10; }
.modal { z-index: 1000; }
.tooltip { z-index: 1100; }
.notification { z-index: 9999; }

Принято иметь шкалу: компоненты 10-99, модалки 100-999, уведомления 1000+.

Свойства top, right, bottom, left

/* Для absolute/fixed — расстояние от края родителя/вьюпорта */
.el { position: absolute; top: 0; right: 0; }  /* Верхний правый угол */
.el { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); }  /* По центру снизу */

/* Центрирование absolute-элемента */
.overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Типичные ошибки

Ошибка 1: absolute без positioned-родителя

/* Значок хочет быть в углу карточки, но улетает к body */
.card { }  /* static — не контекст! */
.card .badge { position: absolute; top: 8px; right: 8px; }

/* Исправление */
.card { position: relative; }  /* Теперь .badge позиционируется относительно .card */

Ошибка 2: z-index без position

.popup { z-index: 999; }  /* Не работает! Элемент static */
.popup { position: relative; z-index: 999; }  /* Работает */

Ошибка 3: sticky не работает

/* sticky не работает, если родитель имеет overflow: hidden или auto */
.container { overflow: hidden; }  /* Убивает sticky у дочерних элементов */

В реальных проектах

Почти каждый интерфейсный компонент использует позиционирование: dropdown-меню (absolute), модальные окна (fixed), тултипы (absolute), фиксированный хедер (fixed), прилипающие фильтры (sticky). Это один из самых используемых инструментов CSS.

Примеры

Позиционирование: карточка с бейджем и фиксированный хедер

// Фиксированный хедер
const header = document.createElement('header')
header.style.position = 'fixed'
header.style.top = '0'
header.style.left = '0'
header.style.right = '0'
header.style.height = '56px'
header.style.backgroundColor = '#1a202c'
header.style.color = 'white'
header.style.display = 'flex'
header.style.alignItems = 'center'
header.style.padding = '0 24px'
header.style.zIndex = '100'
header.textContent = 'Интернет-магазин'
document.body.appendChild(header)

// Отступ под хедер
document.body.style.paddingTop = '72px'

// Карточка с абсолютным бейджем
const card = document.createElement('div')
card.style.position = 'relative'  // Контекст для badge!
card.style.width = '200px'
card.style.height = '200px'
card.style.backgroundColor = '#f7fafc'
card.style.border = '1px solid #e2e8f0'
card.style.borderRadius = '12px'
card.style.margin = '16px'
card.textContent = 'Кроссовки Nike'
document.body.appendChild(card)

// Бейдж "Хит" в верхнем правом углу карточки
const badge = document.createElement('span')
badge.textContent = 'ХИТ'
badge.style.position = 'absolute'
badge.style.top = '8px'
badge.style.right = '8px'
badge.style.backgroundColor = '#e53e3e'
badge.style.color = 'white'
badge.style.fontSize = '10px'
badge.style.fontWeight = '700'
badge.style.padding = '2px 6px'
badge.style.borderRadius = '4px'
card.appendChild(badge)

// Читаем позиционирование
const headerStyle = window.getComputedStyle(header)
console.log('Хедер position:', headerStyle.position)    // fixed
console.log('Хедер top:', headerStyle.top)              // 0px
console.log('Хедер z-index:', headerStyle.zIndex)       // 100

const badgeStyle = window.getComputedStyle(badge)
console.log('Бейдж position:', badgeStyle.position)     // absolute
console.log('Бейдж top:', badgeStyle.top)               // 8px
console.log('Бейдж right:', badgeStyle.right)           // 8px

const cardStyle = window.getComputedStyle(card)
console.log('Карточка position:', cardStyle.position)   // relative (контекст для бейджа)

Позиционирование элементов

Меню, которое остаётся наверху при прокрутке. Значок "Новое!" в углу карточки. Модальное окно по центру экрана. Всё это — CSS-позиционирование. Пять значений position, и каждое решает свою задачу.

position: static (по умолчанию)

Все элементы изначально статичны — они стоят в нормальном потоке: один за другим, сверху вниз (block) или слева направо (inline). Свойства top, left, right, bottom при static не работают.

div { position: static; }  /* Это поведение по умолчанию */

position: relative

Элемент остаётся в потоке, но может быть сдвинут от своего нормального места.

.badge {
  position: relative;
  top: 5px;    /* Сдвиг вниз от нормального места */
  left: -3px;  /* Сдвиг влево */
}

Важно: место в потоке сохраняется — соседние элементы не двигаются.

Главное применение relative — создать контекст позиционирования для дочерних absolute-элементов.

position: absolute

Элемент вырывается из потока — соседи его не видят, он парит над ними. Позиционируется относительно ближайшего предка с position не равным static.

/* Родитель — контекст позиционирования */
.card {
  position: relative;  /* Без этого absolute уйдёт к body! */
}

/* Значок в углу карточки */
.card .badge {
  position: absolute;
  top: 8px;
  right: 8px;
  background: red;
  border-radius: 50%;
}

Если у элемента нет positioned-предка, он позиционируется относительно <html>.

position: fixed

Привязан к вьюпорту (экрану), не к странице. Не скроллится вместе с контентом.

/* Шапка сайта, которая всегда вверху */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;  /* или width: 100% */
  z-index: 100;
  background: white;
}

/* Кнопка "Наверх" в правом нижнем углу */
.scroll-top-btn {
  position: fixed;
  bottom: 24px;
  right: 24px;
}

Проблема: fixed элемент перекрывает контент. Нужно добавлять padding-top к body, равный высоте хедера.

position: sticky

Гибрид: ведёт себя как relative, пока не достигнет указанного порога при скролле — тогда "прилипает" как fixed.

/* Заголовок таблицы, который прилипает при скролле */
thead th {
  position: sticky;
  top: 0;
  background: white;
}

/* Боковая навигация, которая следует за скроллом */
.sidebar {
  position: sticky;
  top: 80px;  /* 80px от верха вьюпорта */
}

z-index — слои

Определяет порядок по оси Z (что поверх чего). Работает только для позиционированных элементов.

.dropdown { z-index: 10; }
.modal { z-index: 1000; }
.tooltip { z-index: 1100; }
.notification { z-index: 9999; }

Принято иметь шкалу: компоненты 10-99, модалки 100-999, уведомления 1000+.

Свойства top, right, bottom, left

/* Для absolute/fixed — расстояние от края родителя/вьюпорта */
.el { position: absolute; top: 0; right: 0; }  /* Верхний правый угол */
.el { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); }  /* По центру снизу */

/* Центрирование absolute-элемента */
.overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Типичные ошибки

Ошибка 1: absolute без positioned-родителя

/* Значок хочет быть в углу карточки, но улетает к body */
.card { }  /* static — не контекст! */
.card .badge { position: absolute; top: 8px; right: 8px; }

/* Исправление */
.card { position: relative; }  /* Теперь .badge позиционируется относительно .card */

Ошибка 2: z-index без position

.popup { z-index: 999; }  /* Не работает! Элемент static */
.popup { position: relative; z-index: 999; }  /* Работает */

Ошибка 3: sticky не работает

/* sticky не работает, если родитель имеет overflow: hidden или auto */
.container { overflow: hidden; }  /* Убивает sticky у дочерних элементов */

В реальных проектах

Почти каждый интерфейсный компонент использует позиционирование: dropdown-меню (absolute), модальные окна (fixed), тултипы (absolute), фиксированный хедер (fixed), прилипающие фильтры (sticky). Это один из самых используемых инструментов CSS.

Примеры

Позиционирование: карточка с бейджем и фиксированный хедер

// Фиксированный хедер
const header = document.createElement('header')
header.style.position = 'fixed'
header.style.top = '0'
header.style.left = '0'
header.style.right = '0'
header.style.height = '56px'
header.style.backgroundColor = '#1a202c'
header.style.color = 'white'
header.style.display = 'flex'
header.style.alignItems = 'center'
header.style.padding = '0 24px'
header.style.zIndex = '100'
header.textContent = 'Интернет-магазин'
document.body.appendChild(header)

// Отступ под хедер
document.body.style.paddingTop = '72px'

// Карточка с абсолютным бейджем
const card = document.createElement('div')
card.style.position = 'relative'  // Контекст для badge!
card.style.width = '200px'
card.style.height = '200px'
card.style.backgroundColor = '#f7fafc'
card.style.border = '1px solid #e2e8f0'
card.style.borderRadius = '12px'
card.style.margin = '16px'
card.textContent = 'Кроссовки Nike'
document.body.appendChild(card)

// Бейдж "Хит" в верхнем правом углу карточки
const badge = document.createElement('span')
badge.textContent = 'ХИТ'
badge.style.position = 'absolute'
badge.style.top = '8px'
badge.style.right = '8px'
badge.style.backgroundColor = '#e53e3e'
badge.style.color = 'white'
badge.style.fontSize = '10px'
badge.style.fontWeight = '700'
badge.style.padding = '2px 6px'
badge.style.borderRadius = '4px'
card.appendChild(badge)

// Читаем позиционирование
const headerStyle = window.getComputedStyle(header)
console.log('Хедер position:', headerStyle.position)    // fixed
console.log('Хедер top:', headerStyle.top)              // 0px
console.log('Хедер z-index:', headerStyle.zIndex)       // 100

const badgeStyle = window.getComputedStyle(badge)
console.log('Бейдж position:', badgeStyle.position)     // absolute
console.log('Бейдж top:', badgeStyle.top)               // 8px
console.log('Бейдж right:', badgeStyle.right)           // 8px

const cardStyle = window.getComputedStyle(card)
console.log('Карточка position:', cardStyle.position)   // relative (контекст для бейджа)

Задание

Напиши HTML-страницу с карточкой товара и бейджем "ХИТ" в правом верхнем углу. Карточка — div 200×200px с position: relative. Бейдж — дочерний span с position: absolute, top: 8px, right: 8px, красным фоном. Также добавь синий квадрат 40×40px в нижнем левом углу карточки через position: absolute, bottom: 0, left: 0.

Подсказка

Карточка: position: relative (без этого дочерние absolute уйдут к body). Бейдж: position: absolute, top: 8px, right: 8px. Синий квадрат: position: absolute, bottom: 0, left: 0. Значения top/right/bottom/left без кавычек в CSS: top: 8px (не "8px").

Загружаем среду выполнения...
Загружаем AI-помощника...