JSFiddle - React, Tailwind, and code Playground
HTML
<!-- Родитель с относительным позиционированием -->
<div class="block">
<!-- Блок, который будем замедлять -->
<div class="first"></div>
<!-- Обычный блок -->
<div class="simple"></div>
</div>
CSS
.first {
position: absolute;
z-index: 20;
top: 150px;
left: 30px;
width: 50px;
height: 50px;
background: #343434;
}
.first.fixed {
position: fixed;
z-index: 20;
top: 90px;
}
.simple {
background: green;
margin-top: 140px;
width: 50px;
height: 50px;
margin-left: 100px;
}
.block {
width: 500px;
height: 1100px;
background: #eaeaea;
overflow: hidden;
}
JavaScript
// Наш элемент, который будет замедляться
var $element = $('.first'),
/*
* Последняя позиция скролла, нужна
* для вычисления
*/
lastScrollTop = 0,
/*
* Отступ сверху для нашего блока
* с фиксированным и абсолютным
* позиционированием
*/
defaultElementAbsoluteTop = 150,
defaultElementFixedTop = 90,
// Коэффициэнт замедления
n = 4;
// Отслеживаем скролл страницы
$(window).scroll(function (event) {
// Вычисляем текущее положение
var scrollTop = $(window).scrollTop(),
/*
* Вычисляем положение нашего блока
* от верхней части сайта/родителя.
* Т.к. этот элемент до этого был абсолютным,
* то у него отступ сверху всегда одинаков,
* А когда подходит момент, когда нужно его фиксировать
* отступ расчитывается от последнего, который был
* 150 пикселей. Это неправильно. Я ввел проверку,
* Если отступ стандартный абсолютный равен
* текущему, то, при фиксировании блока
* ставим ему оступ фиксированного блока
* и отсюда начинаются правильные расчеты
*/
elementTop = $element.position().top == defaultElementAbsoluteTop ? defaultElementFixedTop : $element.position().top;
if(scrollTop < 60)
{
/*
* Проскролили меньше, чем на 60 пикселей
* То оставляем абсолютное позиционирование
*/
$element.removeClass('fixed');
// И ставим элементу абсолютный отступ сверху
$element.css({
top: defaultElementAbsoluteTop
});
}
else
{
// Фиксируем элемент
$element.addClass('fixed');
// TODO: удалить!
//return;
/*
* Если прошлое положение меньше,
* чем текущее, значит двигаемся <вниз>
*/
if (scrollTop > lastScrollTop){
// Вычисляем разницу перемещения
var diff = scrollTop - lastScrollTop;
// Даем отступ...