Создание элемента, который фиксируется при прокрутке

Тренажер по работе с HTML DOM на JavaScript для пользователей с начальным и средним уровнем подготовки.

Тренажер JavaScript: Покоряем HTML DOM

В этой серии заданий вы попрактикуетесь в создании 'липкого' элемента (sticky element) — такого, который остается зафиксированным в верхней части окна просмотра при прокрутке страницы вниз. Вы начнете с выбора элемента, определения точки 'прилипания', добавления обработчика событий прокрутки и, наконец, будете динамически изменять стили элемента для достижения эффекта фиксации. Задания построены от простого к сложному, помогая закрепить навыки работы с DOM, событиями и стилями.

Список тем

Выбор элемента для фиксации

Ваша первая задача — получить ссылку на HTML-элемент, который мы будем делать 'липким'. Используйте подходящий метод для выбора элемента по его уникальному идентификатору 'sticky-header'.

CSS
body {
  min-height: 150vh; /* Добавляем высоту для возможности прокрутки */
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
}

.content {
  padding: 20px;
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum.</p>
  <p>Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
  <p>Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor.</p>
</div>
JavaScript
const header = document.input__1("sticky-header");

// Выведем элемент в консоль, чтобы убедиться, что он найден
console.log(header);
Чтобы получить элемент по его ID, используйте метод `document.getElementById('ID_элемента')`.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Определение начальной позиции

Чтобы знать, когда фиксировать элемент, нам нужно определить его начальное положение относительно верха документа. Получите значение `offsetTop` для выбранного ранее элемента 'sticky-header' и сохраните его в переменной `stickyOffsetTop`.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
}

.content {
  padding: 20px;
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");

// Получаем расстояние от верха документа до элемента
const stickyOffsetTop = header.input__1;

console.log("Позиция для 'прилипания':", stickyOffsetTop);
Свойство `offsetTop` элемента возвращает расстояние от верхней границы элемента до верхней границы его `offsetParent`. Используйте `element.offsetTop`.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Добавление обработчика прокрутки

Теперь нам нужно отслеживать событие прокрутки страницы. Добавьте обработчик событий к объекту `window`, который будет реагировать на событие `scroll`. В качестве обработчика пока используйте пустую функцию.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
}

.content {
  padding: 20px;
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

function handleScroll() {
  // Логика будет добавлена позже
  console.log("Страница прокручивается!");
}

// Добавляем слушатель события прокрутки
window.input__1(input__2, handleScroll);
Используйте метод `addEventListener` у объекта `window`. Первый аргумент - название события ('scroll'), второй - функция-обработчик.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Получение текущей прокрутки

Внутри функции `handleScroll` нам нужно знать, насколько страница прокручена по вертикали. Получите текущее значение вертикальной прокрутки окна (`window`) и выведите его в консоль.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
}

.content {
  padding: 20px;
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

function handleScroll() {
  // Получаем текущую позицию прокрутки
  const currentScroll = window.input__1;
  console.log("Текущая прокрутка:", currentScroll);
}

window.addEventListener("scroll", handleScroll);
Используйте свойство `window.pageYOffset` (или его псевдоним `window.scrollY`) для получения текущей вертикальной прокрутки.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Проверка условия для фиксации

Теперь сравним текущую позицию прокрутки (`currentScroll`) с начальной позицией элемента (`stickyOffsetTop`). Добавьте условный оператор `if`, который будет срабатывать, если прокрутка стала больше или равна начальной позиции элемента.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
}

.content {
  padding: 20px;
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

function handleScroll() {
  const currentScroll = window.pageYOffset;

  // Проверяем, достигли ли мы точки 'прилипания'
  if (currentScroll input__1 stickyOffsetTop) {
    console.log("Пора фиксировать!");
    // Действия для фиксации будут здесь
  } else {
    console.log("Еще не время...");
    // Действия для открепления будут здесь
  }
}

window.addEventListener("scroll", handleScroll);
Используйте оператор `>` для сравнения `currentScroll` и `stickyOffsetTop` в условии `if (условие) { ... }`.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Добавление класса для фиксации

Когда условие для фиксации выполняется (прокрутка больше или равна `stickyOffsetTop`), добавьте класс 'sticky' к нашему элементу `header`. Используйте свойство `classList` и его метод `add`.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
  /* Важно: Добавляем transition для плавности */
  transition: all 0.3s ease;
}

.content {
  padding: 20px;
}

/* Стили для фиксированного состояния */
.sticky {
  position: fixed;
  top: 0;
  left: 0; /* Добавлено для корректного позиционирования */
  right: 0; /* Добавлено для корректного позиционирования */
  z-index: 1000;
  background-color: lightcoral; /* Изменим цвет для наглядности */
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

function handleScroll() {
  const currentScroll = window.pageYOffset;

  if (currentScroll > stickyOffsetTop) {
    // Добавляем класс 'sticky'
    header.input__1.input__2("sticky");
  } else {
    // Действия для открепления будут позже
  }
}

window.addEventListener("scroll", handleScroll);
Чтобы добавить класс элементу, используйте `element.classList.add('имя_класса')`.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Удаление класса при откреплении

Теперь реализуйте обратное действие: когда пользователь прокручивает страницу обратно вверх и текущая прокрутка становится меньше `stickyOffsetTop`, удалите класс 'sticky' у элемента `header`. Используйте соответствующий метод `classList`.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
  transition: all 0.3s ease;
}

.content {
  padding: 20px;
}

.sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background-color: lightcoral;
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

function handleScroll() {
  const currentScroll = window.pageYOffset;

  if (currentScroll > stickyOffsetTop) {
    header.classList.add("sticky");
  } else {
    // Удаляем класс 'sticky'
    header.classList.input__1("sticky");
  }
}

window.addEventListener("scroll", handleScroll);
Чтобы удалить класс у элемента, используйте `element.classList.remove('имя_класса')`.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Создание плейсхолдера

Когда элемент становится `position: fixed`, он 'выпадает' из потока документа, и контент под ним резко подпрыгивает вверх. Чтобы этого избежать, создайте новый `div` элемент (плейсхолдер) с помощью JavaScript и сохраните его в переменной `placeholder`.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
  transition: background-color 0.3s ease;
}

.content {
  padding: 20px;
}

.sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background-color: lightcoral;
}

/* Стили для плейсхолдера (пока невидимый) */
.placeholder {
  /* Высота будет задана через JS */
  /* background-color: #eee; /* Для отладки */
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

// Создаем элемент-плейсхолдер
const placeholder = document.input__1("div");

console.log("Плейсхолдер создан:", placeholder);

function handleScroll() {
  const currentScroll = window.pageYOffset;

  if (currentScroll > stickyOffsetTop) {
    header.classList.add("sticky");
  } else {
    header.classList.remove("sticky");
  }
}

window.addEventListener("scroll", handleScroll);
Используйте `document.createElement('div')` для создания нового элемента `div`.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Настройка и вставка плейсхолдера

Настройте созданный плейсхолдер: добавьте ему класс 'placeholder' и установите его высоту равной высоте 'липкого' элемента (`header.offsetHeight`). Затем вставьте плейсхолдер в DOM перед 'липким' элементом.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
  transition: background-color 0.3s ease;
}

.content {
  padding: 20px;
}

.sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background-color: lightcoral;
}

.placeholder {
  /* Высота будет задана через JS */
  /* background-color: #eee; /* Для отладки */
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet...</p>
  <p>Praesent mauris...</p>
  <p>Curabitur sodales...</p>
</div>
JavaScript
const header = document.getElementById("sticky-header");
const stickyOffsetTop = header.offsetTop;

// Создаем и настраиваем плейсхолдер
const placeholder = document.createElement("div");
placeholder.classList.add("placeholder");
placeholder.style.height = header.input__1 + "px";
placeholder.style.display = "none"; // Скроем его по умолчанию

// Вставляем плейсхолдер перед header
header.input__2.input__3(placeholder, header);

function handleScroll() {
  const currentScroll = window.pageYOffset;

  if (currentScroll > stickyOffsetTop) {
    header.classList.add("sticky");
    placeholder.style.display = "block"; // Показываем плейсхолдер
  } else {
    header.classList.remove("sticky");
    placeholder.style.display = "none"; // Скрываем плейсхолдер
  }
}

window.addEventListener("scroll", handleScroll);
Используйте `placeholder.classList.add('placeholder')`, `placeholder.style.height = element.offsetHeight + 'px'`, и `element.parentNode.insertBefore(newNode, referenceNode)` для вставки.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку

Полный код с пропусками

Теперь соберите все вместе. Заполните пропуски, чтобы реализовать полнофункциональный 'липкий' элемент с плейсхолдером для компенсации высоты.

CSS
body {
  min-height: 150vh;
  margin: 0;
  font-family: sans-serif;
}

#sticky-header {
  background-color: lightblue;
  padding: 15px;
  text-align: center;
  border-bottom: 1px solid #ccc;
  transition: background-color 0.3s ease;
}

.content {
  padding: 20px;
}

.sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background-color: lightcoral;
}

/* Плейсхолдер для компенсации высоты */
.placeholder {
  /* Высота задается через JS */
}
HTML
Восстановить HTML
<div id="sticky-header">
  Я буду липким!
</div>
<div class="content">
  <p>Прокручивайте страницу вниз...</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero.</p>
  <img src="/img/1.png" alt="Example Image 1" width="300">
  <p>Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.</p>
  <img src="/img/2.png" alt="Example Image 2" width="300">
  <p>Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta.</p>
</div>
JavaScript
// 1. Находим 'липкий' элемент
const header = document.input__1("sticky-header");

// 2. Получаем его начальное смещение сверху
const stickyOffsetTop = header.input__2;

// 3. Создаем и настраиваем плейсхолдер
const placeholder = document.input__3("div");
placeholder.classList.add("placeholder");
placeholder.style.height = header.input__4 + "px";
placeholder.style.display = "none"; // Скрываем по умолчанию

// Вставляем плейсхолдер в DOM перед header
header.parentNode.insertBefore(placeholder, header);

// 4. Функция-обработчик прокрутки
function handleStickyHeader() {
  // 5. Получаем текущую прокрутку
  const currentScroll = window.input__5;

  // 6. Проверяем условие для 'прилипания'
  if (currentScroll > stickyOffsetTop) {
    // 7. Фиксируем: добавляем класс и показываем плейсхолдер
    header.classList.input__6("sticky");
    placeholder.style.display = "block";
  } else {
    // 7. Открепляем: удаляем класс и скрываем плейсхолдер
    header.classList.input__7("sticky");
    placeholder.style.display = "none";
  }
}

// 8. Добавляем слушатель события прокрутки
window.input__8("scroll", handleStickyHeader);
Вспомните шаги: 1. Выбрать элемент (`getElementById`). 2. Получить его смещение (`offsetTop`). 3. Создать плейсхолдер (`createElement`), задать ему высоту (`offsetHeight`) и вставить (`insertBefore`). 4. Добавить обработчик на `window` для события `scroll` (`addEventListener`). 5. В обработчике получить прокрутку (`pageYOffset`). 6. Сравнить прокрутку со смещением (`>`). 7. Добавлять/удалять (`classList.add`/`remove`) класс 'sticky' и показывать/скрывать (`style.display`) плейсхолдер.
Заполнить ответами все поля
Результат
Лог
Выполнить
Отметить решенным
Показать подсказку
НайтиКурс.Ру
Добавить комментарий