Меню, которое остаётся наверху при прокрутке. Значок "Новое!" в углу карточки. Модальное окно по центру экрана. Всё это — CSS-позиционирование. Пять значений position, и каждое решает свою задачу.
Все элементы изначально статичны — они стоят в нормальном потоке: один за другим, сверху вниз (block) или слева направо (inline). Свойства top, left, right, bottom при static не работают.
div { position: static; } /* Это поведение по умолчанию */Элемент остаётся в потоке, но может быть сдвинут от своего нормального места.
.badge {
position: relative;
top: 5px; /* Сдвиг вниз от нормального места */
left: -3px; /* Сдвиг влево */
}Важно: место в потоке сохраняется — соседние элементы не двигаются.
Главное применение relative — создать контекст позиционирования для дочерних absolute-элементов.
Элемент вырывается из потока — соседи его не видят, он парит над ними. Позиционируется относительно ближайшего предка с position не равным static.
/* Родитель — контекст позиционирования */
.card {
position: relative; /* Без этого absolute уйдёт к body! */
}
/* Значок в углу карточки */
.card .badge {
position: absolute;
top: 8px;
right: 8px;
background: red;
border-radius: 50%;
}Если у элемента нет positioned-предка, он позиционируется относительно <html>.
Привязан к вьюпорту (экрану), не к странице. Не скроллится вместе с контентом.
/* Шапка сайта, которая всегда вверху */
.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, равный высоте хедера.
Гибрид: ведёт себя как relative, пока не достигнет указанного порога при скролле — тогда "прилипает" как fixed.
/* Заголовок таблицы, который прилипает при скролле */
thead th {
position: sticky;
top: 0;
background: white;
}
/* Боковая навигация, которая следует за скроллом */
.sidebar {
position: sticky;
top: 80px; /* 80px от верха вьюпорта */
}Определяет порядок по оси Z (что поверх чего). Работает только для позиционированных элементов.
.dropdown { z-index: 10; }
.modal { z-index: 1000; }
.tooltip { z-index: 1100; }
.notification { z-index: 9999; }Принято иметь шкалу: компоненты 10-99, модалки 100-999, уведомления 1000+.
/* Для 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, и каждое решает свою задачу.
Все элементы изначально статичны — они стоят в нормальном потоке: один за другим, сверху вниз (block) или слева направо (inline). Свойства top, left, right, bottom при static не работают.
div { position: static; } /* Это поведение по умолчанию */Элемент остаётся в потоке, но может быть сдвинут от своего нормального места.
.badge {
position: relative;
top: 5px; /* Сдвиг вниз от нормального места */
left: -3px; /* Сдвиг влево */
}Важно: место в потоке сохраняется — соседние элементы не двигаются.
Главное применение relative — создать контекст позиционирования для дочерних absolute-элементов.
Элемент вырывается из потока — соседи его не видят, он парит над ними. Позиционируется относительно ближайшего предка с position не равным static.
/* Родитель — контекст позиционирования */
.card {
position: relative; /* Без этого absolute уйдёт к body! */
}
/* Значок в углу карточки */
.card .badge {
position: absolute;
top: 8px;
right: 8px;
background: red;
border-radius: 50%;
}Если у элемента нет positioned-предка, он позиционируется относительно <html>.
Привязан к вьюпорту (экрану), не к странице. Не скроллится вместе с контентом.
/* Шапка сайта, которая всегда вверху */
.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, равный высоте хедера.
Гибрид: ведёт себя как relative, пока не достигнет указанного порога при скролле — тогда "прилипает" как fixed.
/* Заголовок таблицы, который прилипает при скролле */
thead th {
position: sticky;
top: 0;
background: white;
}
/* Боковая навигация, которая следует за скроллом */
.sidebar {
position: sticky;
top: 80px; /* 80px от верха вьюпорта */
}Определяет порядок по оси Z (что поверх чего). Работает только для позиционированных элементов.
.dropdown { z-index: 10; }
.modal { z-index: 1000; }
.tooltip { z-index: 1100; }
.notification { z-index: 9999; }Принято иметь шкалу: компоненты 10-99, модалки 100-999, уведомления 1000+.
/* Для 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").