← Назад к вопросам

Как зафиксировать элемент вверху "контейнера" при скролле?

1.3 Junior🔥 201 комментариев
#HTML и CSS#Браузер и сетевые технологии

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Фиксация элемента вверху контейнера при скролле

Для фиксации элемента вверху контейнера используется CSS свойство position: sticky с top: 0. Это элемент остаёт прилипанным к верху его родительского контейнера при скролле.

Основной способ: position sticky

.header {
  position: sticky;
  top: 0;
  background-color: white;
  z-index: 10; /* Важно! Чтобы скролляемый контент не наезжал */
}

Как это работает:

  1. Элемент находится в нормальном потоке документа
  2. Когда страница скроллится, элемент остаётся приклеенным к верху контейнера (top: 0)
  3. Когда контейнер вышел из viewport, элемент уходит вместе с ним

Полный пример: таблица со sticky header

<div class="table-container">
  <table>
    <thead class="sticky-header">
      <tr>
        <th>Название</th>
        <th>Автор</th>
        <th>Дата</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>Item 1</td><td>Alice</td><td>2024-01-01</td></tr>
      <tr><td>Item 2</td><td>Bob</td><td>2024-01-02</td></tr>
      <!-- Много строк для скролла -->
    </tbody>
  </table>
</div>
.table-container {
  max-height: 500px;
  overflow-y: auto;
}

.sticky-header {
  position: sticky;
  top: 0;
  background-color: #f5f5f5;
  border-bottom: 1px solid #ddd;
  z-index: 10; /* Чтобы header был выше других элементов */
}

table {
  width: 100%;
  border-collapse: collapse;
}

td, th {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #eee;
}

Важный момент: контекст стакирования

Sticky работает только внутри своего родительского контейнера. Когда родитель уходит из viewport, sticky элемент уходит вместе с ним:

<section class="container">
  <h2 class="sticky-title">Section 1</h2>
  <p>Content 1</p>
  <p>Content 1</p>
  <!-- При скролле h2 остаётся вверху, пока контент section виден -->
</section>

<section class="container">
  <h2 class="sticky-title">Section 2</h2>
  <p>Content 2</p>
  <!-- Когда скроллим ниже, h2 из первого section уходит -->
</section>
.sticky-title {
  position: sticky;
  top: 0;
  background-color: white;
  font-weight: bold;
  z-index: 10;
}

.container {
  border: 1px solid #ddd;
  margin-bottom: 20px;
  padding: 20px;
}

Sticky vs Fixed

Важно различать эти подходы:

/* FIXED — зафиксирован на экране, не прилипает к контейнеру */
position: fixed;
top: 0;
width: 100%; /* Обычно требуется */
z-index: 999; /* Обычно нужен высокий z-index */
/* Элемент ВСЕГДА видна, даже при скролле */

/* STICKY — прилипает к контейнеру, уходит вместе с ним */
position: sticky;
top: 0;
/* Элемент видна, пока контейнер в viewport */

Практический пример: sticky nav в React

function ProductList() {
  return (
    <div className="products-container">
      {categories.map((category) => (
        <section key={category.id} className="category">
          {/* Sticky заголовок категории */}
          <h2 className="sticky-category-title">
            {category.name}
          </h2>
          
          {category.products.map((product) => (
            <div key={product.id} className="product-card">
              {product.name}
            </div>
          ))}
        </section>
      ))}
    </div>
  );
}
.products-container {
  max-height: 600px;
  overflow-y: auto;
}

.category {
  margin-bottom: 20px;
}

.sticky-category-title {
  position: sticky;
  top: 0;
  background-color: white;
  padding: 12px;
  border-bottom: 2px solid #007bff;
  font-size: 18px;
  font-weight: bold;
  z-index: 10;
}

.product-card {
  padding: 12px;
  border: 1px solid #eee;
  margin-bottom: 8px;
}

Sticky с offset (не на самый верх)

Можно поместить sticky не совсем вверху, а с отступом:

.sticky-element {
  position: sticky;
  top: 60px; /* Не на верх, а на 60px ниже */
  background-color: white;
}

Это полезно, если выше есть фиксированный header (fixed).

Проблемы и решения

Проблема 1: overflow: hidden на родителе

/* ❌ Sticky не работает */
.parent {
  overflow: hidden;
}

.child {
  position: sticky;
  top: 0;
}

/* ✅ Решение: используй overflow: auto или visible */
.parent {
  overflow: auto; /* Или не указывай overflow */
}

Проблема 2: z-index не работает правильно

/* ✅ Убедись, что z-index достаточно высокий */
.sticky-header {
  position: sticky;
  top: 0;
  z-index: 10; /* Больше, чем у скролляемого контента */
  background-color: white; /* Обязательно! Иначе контент видна через */
}

Резюме

position: sticky с top: 0 — это стандартный способ прилепить элемент к верху контейнера при скролле. Ключевые моменты:

  • Элемент остаётся в потоке документа
  • Работает только в пределах родительского контейнера
  • Нужен background-color или z-index для правильного отображения
  • Не работает с overflow: hidden на родителе
  • Поддерживается всеми современными браузерами