JSFiddle - React, Tailwind, and code Playground
HTML
<div class="wrapper">
<div class="clouds">
<div class="cloud" style="top: 120px; left: 275px"></div>
<div class="cloud" style="top: 76px; left: 175px"></div> <div class="cloud" style="top: 258px; left: 205px"></div>
<div class="cloud" style="top: 204px; left: 45px"></div>
<div class="cloud" style="top: 40px; left: 175px"></div>
<div class="cloud" style="top: 186px; left: 83px"></div>
<div class="cloud" style="top: 137px; left: 70px"></div>
<div class="cloud" style="top: 37px; left: 50px"></div>
<div class="cloud" style="top: 170px; left: 90px"></div>
</div>
</div>
CSS
.wrapper {
margin-top: 100vh;
overflow: hidden;
height: 300px;
width: 300px;
background-color: grey;
position: relative;
}
.cloud {
position: absolute;
width: 10px;
height: 10px;
background-color: #000;
}
JavaScript
let offset = 100; // Нужна для того, чтобы анимация запускалась не сразу же после прокрутки до элемента
let wrapperTop = getCoords(document.querySelector('.wrapper')).top + offset;
let array = document.querySelectorAll('.cloud');
let range = 2; // Сделал её специально, чтобы блоки двигались с разной скоростью, можете указать её как 1
let interval;
array.forEach((el) => {
el.step = Math.ceil(Math.random() * range);
})
window.addEventListener('scroll', () => {
let windowPos = window.innerHeight + window.scrollY;
if (windowPos >= wrapperTop)
if (!interval) {
interval = setInterval(swim, 10);
}
})
function swim() { // "Заставляет" плавать наши облака
array.forEach((el) => {
let posLeft = parseInt(getComputedStyle(el).left);
el.style.left = posLeft - el.step + 'px';
if (posLeft < -el.offsetWidth) {
el.style.left = el.offsetParent.offsetWidth + el.offsetWidth + 'px';
}
})
}
function getCoords(elem) { // Получение координат относительно документа
var box = elem.getBoundingClientRect();
return {
top: box.top + pageYOffset,
left: box.left + pageXOffset
};
}