2

I have seen many sites load whenever you scroll. How to do the same thing on my site?

1

2 Answers 2

1

It would be better if you provide us an example what websites you mean. Ok. I will imagine that you are talking about a website like Pinterest that shows you content as much as you scroll it. It is not hard. You just have to get data from a server when user is for example at the end of the page

  1. Add a listener on the scroll
window.addEventListener("scroll", scrollHandler);
  1. Find out if a user is at the end of a page in the scroll listener:
const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight;
  1. Get new content from a server
  2. Add new content to a page

Example:

const cardContainer = document.getElementById("card-container");
const cardCountElem = document.getElementById("card-count");
const cardTotalElem = document.getElementById("card-total");
const loader = document.getElementById("loader");

const cardLimit = 99;
const cardIncrease = 9;
const pageCount = Math.ceil(cardLimit / cardIncrease);
let currentPage = 1;

cardTotalElem.innerHTML = cardLimit;

var throttleTimer;
const throttle = (callback, time) => {
  if (throttleTimer) return;

  throttleTimer = true;

  setTimeout(() => {
    callback();
    throttleTimer = false;
  }, time);
};

const getRandomColor = () => {
  const h = Math.floor(Math.random() * 360);

  return `hsl(${h}deg, 90%, 85%)`;
};

const createCard = (index) => {
  const card = document.createElement("div");
  card.className = "card";
  card.innerHTML = index;
  card.style.backgroundColor = getRandomColor();
  cardContainer.appendChild(card);
};

const addCards = (pageIndex) => {
  currentPage = pageIndex;

  const startRange = (pageIndex - 1) * cardIncrease;
  const endRange =
    currentPage == pageCount ? cardLimit : pageIndex * cardIncrease;

  cardCountElem.innerHTML = endRange;

  for (let i = startRange + 1; i <= endRange; i++) {
    createCard(i);
  }
};

const handleInfiniteScroll = () => {
  throttle(() => {
    const endOfPage =
      window.innerHeight + window.pageYOffset >= document.body.offsetHeight;

    if (endOfPage) {
      addCards(currentPage + 1);
    }

    if (currentPage === pageCount) {
      removeInfiniteScroll();
    }
  }, 1000);
};

const removeInfiniteScroll = () => {
  loader.remove();
  window.removeEventListener("scroll", handleInfiniteScroll);
};

window.onload = function () {
  addCards(currentPage);
};

window.addEventListener("scroll", handleInfiniteScroll);
body {
  font-family: "Roboto", sans-serif;
}

#card-container {
  display: flex;
  flex-wrap: wrap;
}

.card {
  height: 55vh;
  width: calc((100% / 3) - 16px);
  margin: 8px;
  border-radius: 3px;
  transition: all 200ms ease-in-out;
  display: flex;
  align-items: center;
  justify-content: center;
}

.card:hover {
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}

.card-actions {
  margin: 8px;
  padding: 16px 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

#loader {
  display: flex;
}

.skeleton-card {
  height: 55vh;
  width: calc((100% / 3) - 16px);
  margin: 8px;
  border-radius: 3px;
  transition: all 200ms ease-in-out;
  position: relative;
  background-color: #eaeaea;
}

.skeleton-card::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  transform: translateX(-100%);
  background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.2) 20%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0));
  animation: load 1s infinite;
}

@keyframes load {
  100% {
    transform: translateX(100%);
  }
}

@media screen and (prefers-reduced-motion: reduce) {
  .skeleton-card::after {
    animation: none;
  }
}
<div id="card-container">
</div>
<div id="loader">
  <div class="skeleton-card"></div>
  <div class="skeleton-card"></div>
  <div class="skeleton-card"></div>
</div>
<div class="card-actions">
  <span>Showing 
    <span id="card-count"></span> of 
    <span id="card-total"></span> cards      
  </span>
</div>

Note: It is better to open this example in the full-page mode

The source

Sign up to request clarification or add additional context in comments.

Comments

1

You have to use Intersection Observer API

let options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 1.0
}

let observer = new IntersectionObserver(callback, options);

function callback() {
    // Something like showing a hidden element or css animation
}

The above code will call callback function when the users scrolls over a section with id scrollArea

Here is another example:

const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
        console.log(entry);
        if(entry.isIntersecting) {
            entry.target.classList.add("show");
        } else {
            entry.target.classList.remove("show");
        }
    })
})


const hiddens = document.querySelectorAll(".hidden");
hiddens.forEach(val => {
    observer.observe(val);
});
body {
    font-family: 'Courier New', Courier, monospace;
    background-color: #131316;
    color: #ffffff;
    padding: 0;
    margin: 0;
}

section, h1.cen {
    display: grid;
    place-items: center;
    align-content: center;
    min-height: 100vh;
}

.hidden {
    opacity: 0;
    transition: all 3s;
}

.show {
    opacity: 1;
    
}
<!DOCTYPE html>
<html lang="en">
<head>
    <title>SCROLL</title>
</head>
<body>
    <h1 class="cen">Scroll more</h1>
    <section class="hidden">
        <h1>Hello World</h1>
        <p>This is my scroll animation website</p>
    </section>

    <section class="hidden">
        <h2>Buy my product</h2>
        <p>Just a demo</p>
    </section>

    <section class="hidden">
        <h2>It's really good</h2>

    </section>
</body>
</html>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.