Как создать липкий элемент с помощью свойства position: fixed?

Подскажите, пожалуйста, как мне создать липкий заголовок, который бы опускался до границы списка и затем переставал быть липким? Я пробовал использовать библиотеку sticky.js, но она работает некорректно. Поэтому решил написать свою реализацию. У меня возник вопрос: почему в обработчике события скролла оба следующих условия всегда возвращают false, хотя верхняя граница элемента stickyTitle достигается? В результате добавление класса к элементу не происходит. 

Вот коды, которые я использую: 
<br/> 
<pre><code>window.scrollY === stickyTitle.getBoundingClientRect().height</code></pre> 
<br/> 
<pre><code>document.documentElement.scrollTop === stickyTitle.getBoundingClientRect().height</code></pre> 
<br/> 

Полный код обработчика события:
<br/> 
<pre><code class="javascript">window.addEventListener('scroll', () =&gt; {
  console.log(window.scrollY === stickyTitle.getBoundingClientRect().height);
  console.log(document.documentElement.scrollTop === stickyTitle.getBoundingClientRect().height);

  if (document.documentElement.scrollTop === stickyTitle.getBoundingClientRect().height) {
    stickyTitle.classList.add('sticky')
  }
})</code></pre> 
<br/> 

Класс для липкого заголовка:
<br/> 
<pre><code>.sticky {
  position: fixed;
  left: 205px;
  top: 120px;
  width: 37%;
}</code></pre> 
<br/> 

В чём может заключаться проблема?
  • 10 октября 2024 г. 19:34
Ответы на вопрос 2
Скажем так, ваша задача — создать "липкий" заголовок, который будет оставаться вверху экрана, пока пользователь скроллит страницу, но перестанет быть "липким", когда достигнет определенной точки на странице. Кажется, что у вас есть некоторые проблемы в логике определения состояния "липкости". Давайте попробуем разобраться и упростить ваш код.

### Проблема с условиями:

В ваших условиях:
```javascript
window.scrollY === stickyTitle.getBoundingClientRect().height
```
и 
```javascript
document.documentElement.scrollTop === stickyTitle.getBoundingClientRect().height
```
вы сравниваете текущую позицию скролла (в пикселях) с высотой заголовка. Это, скорее всего, не то, что вам нужно. Вместо этого вам следует проверять, когда заголовок достигает верхней части окна и когда он достигает нижней границы списка.

### Предложенное решение:

1. **Определите верхнюю и нижнюю границу**: Запомните, где начинается заголовок и где заканчивается список (или элемент, с которым вы собираетесь его взаимодействовать).

2. **Добавьте и уберите стиль "липкости"**: Используйте проверку на положение скролла, чтобы добавлять и убирать класс.

Используйте следующий пример кода:

```javascript
const stickyTitle = document.querySelector('.sticky-title');
const stickyOffset = stickyTitle.offsetTop; // Позиция заголовка от верхней части страницы
const listBottom = document.querySelector('.list').offsetTop + document.querySelector('.list').offsetHeight; // Конечная позиция списка

window.addEventListener('scroll', () => {
  const scrollPosition = window.scrollY; // Положение скролла

  if (scrollPosition > stickyOffset && scrollPosition < listBottom) {
    stickyTitle.classList.add('sticky');
  } else {
    stickyTitle.classList.remove('sticky');
  }
});
```

### Пояснение кода:

- `offsetTop` используется для получения расстояния от верхней части страницы до верхней границы заголовка.
- `listBottom` рассчитывается как начало списка плюс его высота, что означает, где заканчивается список.
- В обработчике события `scroll`, проверяем, больше ли позиция скролла верхней позиции заголовка и меньше ли она нижней позиции списка. Если это так, добавляем класс `sticky`. В противном случае убираем его.

### CSS стиль:

Ваш CSS-класс для "липкого" заголовка уже правильный, но убедитесь, что у вас корректно настроены другие стили для `sticky-title`, иначе он может не отображаться или может перекрывать другие элементы при применении класса.

Пробуйте использовать этот подход, и вы должны увидеть, что ваш заголовок будет вести себя как ожидается при прокрутке.
Предположу, что событие скролла не вызывается на каждый проскролленный пиксель. А значит ваш код просто "проскакивает" нужную точку. Используйте сравнение >= или <= , в зависимости от вашей логики.
Похожие вопросы